程序集编号更改错误
我试图制作一个汇编程序,它带一个数字,然后打印出来。但是当我写1时,它写了4171.为什么,我该如何解决它?我使用的是64位程序集,我用nasm -f macho64 scanf.asm
组装了它,并且我将它与gcc -o scanf scanf.o -Wl,-no-pie
联系起来。我试图在扫描宏的数字周围使用方括号(用于指向可变数字的指针),但是nasm mach-o不允许它,所以我没有这样做。程序集编号更改错误
这里是我的代码:
; lib.asm
extern _printf
extern _scanf
%macro print 2
push rbp
mov rdi, %1
mov rsi, %2
xor rax, rax
call _printf
pop rbp
%endmacro
%macro scan 2
push rbp
mov rdi, %1
mov rsi, %2
mov rax, 0
call _scanf
pop rbp
%endmacro
; scanf.asm
%INCLUDE "lib.asm"
section .bss
number resd 1
section .text
global _main
_main:
print str_out, qst
scan int_in, number
print ans, number
exit:
mov rax, 0x2000001
xor rbx, rbx
syscall
section .data
str_out db '%s', 0xa, 0
int_in db '%d', 0
int_out db '%d', 0xa, 0
qst db 'Enter a number: ', 0
ans db 'You wrote: %d', 0xa, 0
宏打印的答案不正确。
print ans, number
当宏展开时会得到:
push rbp
mov rdi, ans ; RDI = Address of ans
mov rsi, number ; RSI = Address of number
xor rax, rax
call _printf
pop rbp
我评论过上述2线和它们的含义。格式字符串'You wrote: %d'
表示打印一个整数。您已经通过了number
的地址。要解决此问题,请从number
获取32位值,并将其放置在可用的寄存器中,并将该寄存器传递给您的宏。
要做到这一点,你可以替换:
print ans, number
有了:
mov eax, [rel number] ; Get the 32-bit number from number and store in eax
; Using RIP relative addressing
print ans, rax ; Print the 32-bit word in the bottom half of RAX.
这将扩展为:
push rbp
mov rdi, ans ; RDI = Address of ans
mov rsi, rax ; RSI = number to print in RAX
xor rax, rax
call _printf
pop rbp
注意:我们使用mov eax, [rel number]
与rel
指令改变默认的绝对地址是RIP相对寻址的行为。如果您希望使用mov eax, [number]
并避免必须指定rel
,则可以覆盖缺省寻址并将default rel
置于装配文件的顶部。默认值是default abs
。
你可能会问为什么我建议:
mov eax, [rel number] ; Get the 32-bit number from number and store in eax
; Using RIP relative addressing
print ans, rax ; Print the 32-bit word in the bottom half of RAX.
不是:
print ans, [rel number]
最终,宏将试图做到这一点:
mov rsi, [rel number] ; Get the 64-bit number from number and store in RDI
你定义number
这个方式:
number resd 1
这是一个32位值,而不是64位。 mov rsi, [rel number]
本来会尝试从存储位置number
移动8个字节到RSI。这可能会导致您的示例代码没有问题,但它被认为是不好的形式。尽管它可能有效,但我认为这是一个错误。
它很有效,但我必须在顶部放置'DEFAULT REL'才能解决nasm错误。 – SpilledMango
我在回答的底部发表了一条评论,但它应该已经接受顶部没有'default rel'的'mov eax,[rel number]'。 –
您的'打印答案,号码'似乎在打印出'号码'的地址,而不是号码本身。如果你用'movsx rax,dword [number]''print ans,rax'替换'print ans,number'。在这种情况下'mov eax,[number]''print ans,rax'应该也可以。 –
当我尝试“movsx rax,dword [number]”时,nasm打印“scanf.asm:12:错误:Mach-O 64位格式不支持32位绝对地址”,当我尝试“mov rax,[数]”。 – SpilledMango
好吧试试这样,然后'mov rax,[rel number]'强制它使用相对RIP寻址 –