NASM 32位:printf打印寄存器内容
NASM 32-bit: printing content of register by printf
我是装配新手。对于遵循我预期的简单代码,我有不同的输出。每次调用 printf
之前,eax
的内容都会向右移动一些数字。我究竟做错了什么?谢谢。
代码:
;file name : testing.asm
;assemble and link with:
;nasm -f elf testing.asm && gcc -m32 -o testing testing.o
extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 15 ; int a=15
str: db "content in eax=%d", 10, 0
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
mov ebp, esp
mov eax, [a] ; put a from store into register
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
shr eax, 1
push eax ; eax content should be 1>>1 = 0
push dword str
call printf ; printf(str,content_of_eax)
mov esp, ebp ; takedown stack frame
mov eax, 0 ; normal, no error, return value
ret ; return
输出:
content in eax=7
content in eax=4
content in eax=8
预期输出:
content in eax=7
content in eax=1
content in eax=0
printf
returns其结果在eax
中,原来的值丢失了。
您应该从 [a]
重新加载它或使用跨函数调用保存的寄存器,例如 esi
,但您也应该保存它并在返回给调用者之前恢复它。您应该在每次调用后使用 add esp,8
弹出传递给 printf
的参数,以保持堆栈帧一致。
请记住,printf 会将 return 传输到输出的字符数。所以当你这样做时:
call printf ; printf(str,content_of_eax)
shr eax, 2
您实际上是在移动 printf 的结果:
- "content in eax=7\n" 是 17 个字符,所以 shiftfting by 2 给出:17 / 4 = 4
您需要在移位之前保存该值(在保留的寄存器中、在堆栈中或在内存中)。
这个答案似乎不是一个好的解决方案,由于下面的讨论,我目前保留它
就像其他人所说的那样,printf
会 return 它是 eax 的结果。 printf的结果是写入的字节数。
由于您将 shr
操作的结果压入堆栈,您可以使用 pop
再次检索它们,如下所示:
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
pop eax
pop eax
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
# and so on ...
在您的数据部分中,您可以只对 a
使用等式,因为您只使用该变量一次并且不会更改它(我将其称为 value
)。
fmt db "content in eax=%d",0xa,0
value equ 15
在 main 函数中我很确定(如果我错了请纠正我)你应该在用堆栈指针更新它之前保存基指针。
main:
push ebp
mov ebp, esp
现在您可以创建一个局部变量来存储您正在处理的当前值。
sub esp, 4
从那里开始,您只需在每次调用 printf
之前继续获取、移动和存储堆栈中的值。
mov eax, value ; move 15 into eax
shr eax, 1 ; make first shift
mov dword[ebp-4], eax ; store result in local variable
push eax ; eax = 7
push fmt
call printf
add esp, 8 ; clean eax & fmt off the stack
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 2 ; make second shift
mov dword[ebp-4], eax ; store result back in variable
push eax ; eax = 1
push fmt
call printf
add esp, 8
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 1 ; make last shift
push eax ; eax = 0
push fmt
call printf
add esp, 8
add esp, 4 ; clean local variable
然后请记住,在您 return 之前,当您释放堆栈帧时,您也会恢复(弹出)基指针。
mov esp, ebp
pop ebp
这应该输出:
content in eax=7
content in eax=1
content in eax=0
我是装配新手。对于遵循我预期的简单代码,我有不同的输出。每次调用 printf
之前,eax
的内容都会向右移动一些数字。我究竟做错了什么?谢谢。
代码:
;file name : testing.asm
;assemble and link with:
;nasm -f elf testing.asm && gcc -m32 -o testing testing.o
extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 15 ; int a=15
str: db "content in eax=%d", 10, 0
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
mov ebp, esp
mov eax, [a] ; put a from store into register
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
shr eax, 1
push eax ; eax content should be 1>>1 = 0
push dword str
call printf ; printf(str,content_of_eax)
mov esp, ebp ; takedown stack frame
mov eax, 0 ; normal, no error, return value
ret ; return
输出:
content in eax=7
content in eax=4
content in eax=8
预期输出:
content in eax=7
content in eax=1
content in eax=0
printf
returns其结果在eax
中,原来的值丢失了。
您应该从 [a]
重新加载它或使用跨函数调用保存的寄存器,例如 esi
,但您也应该保存它并在返回给调用者之前恢复它。您应该在每次调用后使用 add esp,8
弹出传递给 printf
的参数,以保持堆栈帧一致。
请记住,printf 会将 return 传输到输出的字符数。所以当你这样做时:
call printf ; printf(str,content_of_eax)
shr eax, 2
您实际上是在移动 printf 的结果:
- "content in eax=7\n" 是 17 个字符,所以 shiftfting by 2 给出:17 / 4 = 4
您需要在移位之前保存该值(在保留的寄存器中、在堆栈中或在内存中)。
这个答案似乎不是一个好的解决方案,由于下面的讨论,我目前保留它
就像其他人所说的那样,printf
会 return 它是 eax 的结果。 printf的结果是写入的字节数。
由于您将 shr
操作的结果压入堆栈,您可以使用 pop
再次检索它们,如下所示:
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
pop eax
pop eax
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
# and so on ...
在您的数据部分中,您可以只对 a
使用等式,因为您只使用该变量一次并且不会更改它(我将其称为 value
)。
fmt db "content in eax=%d",0xa,0
value equ 15
在 main 函数中我很确定(如果我错了请纠正我)你应该在用堆栈指针更新它之前保存基指针。
main:
push ebp
mov ebp, esp
现在您可以创建一个局部变量来存储您正在处理的当前值。
sub esp, 4
从那里开始,您只需在每次调用 printf
之前继续获取、移动和存储堆栈中的值。
mov eax, value ; move 15 into eax
shr eax, 1 ; make first shift
mov dword[ebp-4], eax ; store result in local variable
push eax ; eax = 7
push fmt
call printf
add esp, 8 ; clean eax & fmt off the stack
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 2 ; make second shift
mov dword[ebp-4], eax ; store result back in variable
push eax ; eax = 1
push fmt
call printf
add esp, 8
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 1 ; make last shift
push eax ; eax = 0
push fmt
call printf
add esp, 8
add esp, 4 ; clean local variable
然后请记住,在您 return 之前,当您释放堆栈帧时,您也会恢复(弹出)基指针。
mov esp, ebp
pop ebp
这应该输出:
content in eax=7
content in eax=1
content in eax=0