程序集编号更改错误

问题描述:

我试图制作一个汇编程序,它带一个数字,然后打印出来。但是当我写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 
+0

您的'打印答案,号码'似乎在打印出'号码'的地址,而不是号码本身。如果你用'movsx rax,dword [number]''print ans,rax'替换'print ans,number'。在这种情况下'mov eax,[number]''print ans,rax'应该也可以。 –

+0

当我尝试“movsx rax,dword [number]”时,nasm打印“scanf.asm:12:错误:Mach-O 64位格式不支持32位绝对地址”,当我尝试“mov rax,[数]”。 – SpilledMango

+0

好吧试试这样,然后'mov rax,[rel number]'强制它使用相对RIP寻址 –

宏打印的答案不正确。

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。这可能会导致您的示例代码没有问题,但它被认为是不好的形式。尽管它可能有效,但我认为这是一个错误。

+0

它很有效,但我必须在顶部放置'DEFAULT REL'才能解决nasm错误。 – SpilledMango

+0

我在回答的底部发表了一条评论,但它应该已经接受顶部没有'default rel'的'mov eax,[rel number]'。 –