装配编号更改错误
Assembly number change error
我试图制作一个汇编程序,它取一个数字,然后打印出来。但是当我写 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
我已经评论了上面的两行及其含义。 '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]
会尝试将 8 个字节从内存位置 number
移动到 RSI。这可能不会在您的示例代码中造成任何问题,但它被认为是错误的形式。尽管它可能有效,但我认为它是一个错误。
我试图制作一个汇编程序,它取一个数字,然后打印出来。但是当我写 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
我已经评论了上面的两行及其含义。 '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]
会尝试将 8 个字节从内存位置 number
移动到 RSI。这可能不会在您的示例代码中造成任何问题,但它被认为是错误的形式。尽管它可能有效,但我认为它是一个错误。