我是装配新手。我有不同的输出来跟踪我预期的简单代码。每次调用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
答案 0 :(得分:4)
printf
在eax
中返回其结果,原始值将丢失。
您应该从[a]
重新加载它,或使用在esi
等函数调用中保存的寄存器,但您也应保存它并在返回调用方之前将其恢复。在每次调用后,您应该使用printf
弹出传递给add esp,8
的参数,以保持堆栈帧一致。
答案 1 :(得分:3)
在您的数据部分中,您可以使用等同于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
然后记住,在你返回之前,当你释放堆栈帧时,你也恢复(弹出)基本指针。
mov esp, ebp
pop ebp
这应输出:
content in eax=7
content in eax=1
content in eax=0
答案 2 :(得分:1)
请记住,printf将返回传输到输出的字符数。所以当你这样做时:
call printf ; printf(str,content_of_eax)
shr eax, 2
您实际上是从printf转移结果:
您需要在移位之前保存该值(在保留的寄存器中,在堆栈中或内存中)。
答案 3 :(得分:0)
这个答案似乎不是一个好的解决方案,由于下面的讨论,我目前正在保留它
与其他人一样,printf
会将结果返回给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 ...