我正在努力让idiv
正常工作,而且我已经读过你想要划分的内容
例如25,然后在ebx
中你把你想要除的东西比如5,然后你做
idiv ebx
然后将EAX
= 5然后EDX
= 0。
然而,在我的程序中,我的输入不是 100000000
输出:
Kilobytes:100000000
兆字节:1869375819
想知道我在这里做错了什么?
%include "asm_io.inc"
;
; initialized data is put in the .data segment
;
segment .data
prompt db "Please enter the number of bytes:", 0
param db "1 = Calculate it in kilobytes", 0Ah, "2 = Calculate it in megabytes", 10, 0
output db "Kilobytes: %d", 0Ah, "MegaBytes: %d", 10, 0
;
;
segment .bss
;
input resd 1
input2 resd 1
choice resd 1
;
; code is put in the .text segment
;
segment .text
global asm_main
extern printf
asm_main:
enter 0,0
pusha
mov eax, prompt
call print_string
call read_int
mov [input], eax
mov [input2], eax
sub esp, 10h
push dword [output]
push dword [input2]
push dword [input]
mov eax, param
call print_string
call read_int
cmp eax, 1
je kilobyte; Jump if eax is equal to 1
cmp eax, 2
je megabyte; Jump if eax equal to 2
kilobyte:
pop eax ; Pop input into eax
cdq
mov ebx, 1024 ; Put 1024 into ebx
idiv ebx ; EAX = 100000000/1024 = 97656
mov [input], eax ; Move 97656 into var=input
push dword [input] ; Put into stack
jmp megabyte
megabyte:
pop eax ; Pop input into eax
cdq
mov ebx, 1048576 ; Put 1048576 into ebx
idiv ebx ; EAX = 100000000/1024 = 95
mov [input2], eax ; Move 95 into var=input
push dword [input] ; Put into stack
jmp printOut
printOut:
mov dword [esp], output
call printf
add esp, 4 * 3
add esp, 10h
popa
mov eax, 0
leave
ret
更新
我放入xor edx, edx
但我仍然获得与以前相同的输出。我查看了我的电子书和其他网站,它说同样的事情,所以我真的不确定我做错了什么。还试过idiv
路线没有运气。
答案 0 :(得分:5)
首先,对于你需要的目标(计算MBytes和KBytes),你实际上需要无符号的划分。因此,请使用div
指令代替idiv
。
其次,div
和idiv
实际上将edx:eax
中的64位数除以指定为操作数的32位数。但是您的edx
寄存器包含随机数。
因此,你必须在分割前将eax
中的数字扩展到64位。
idiv
使用:
cdq ; convert signed 32bit number in eax into signed 64bit in edx:eax
idiv ebx
div
使用:
xor edx, edx ; set edx to 0 in order to extend unsigned eax in edx:eax
div ebx
您的打印代码看起来不对:
kilobyte:
pop eax ; Pop input into eax
cdq
mov ebx, 1024 ; Put 1024 into ebx
idiv ebx ; EAX = 100000000/1024 = 97656
mov [input], eax ; Move 97656 into var=input
push dword [input] ; Put into stack
jmp megabyte
megabyte:
pop eax ; Pop input into eax
cdq
mov ebx, 1048576 ; Put 1048576 into ebx
idiv ebx ; EAX = 100000000/1024 = 95
mov [input2], eax ; Move 95 into var=input
push dword [input] ; Put into stack
jmp printOut
printOut:
mov dword [esp], output
call printf
add esp, 4 * 3
首先,为什么要跳到下一个地址??? CPU将自己到达那里。这不是错误的,但会使代码的可读性降低,而且只是多余的。
mov [input2], eax ; Move 95 into var=input
push dword [input] ; Put into stack
printOut:
mov dword [esp], output
call printf
add esp, 4 * 3
在这里你可以看到,结果存储在[input2]中,但[input]被压入堆栈。为什么?下一条指令mov dword [esp], output
将覆盖堆栈中的最后一个推送值。
请注意,推送指令首先递减esp
,然后将推送值存储在[esp]。在这里,您需要push output
。
答案 1 :(得分:4)
您需要初始化EDX - 将其归零(xor edx, edx
)并使用无符号运算,或将EAX扩展到其中(cdq
)
IDIV如下(link):
除以(签名)AX,DX:AX或EDX:EAX寄存器中的值 (被除数)由源操作数(除数)并存储结果 AX(AH:AL),DX:AX或EDX:EAX寄存器。源操作数可以是 通用寄存器或存储器位置。
这个动作 指令取决于操作数大小(被除数/除数),如图所示 在下表中:IDIV结果[header]操作数
由于您要划分EBX,因此需要从EDX:EAX获得红利。您没有将EDX初始化为零,因此得到了垃圾结果。
答案 2 :(得分:1)
结果与您对堆栈的使用一致。
代码的前三个“ push”,将堆栈保留为
当代码到达printOut时,将用printf的字符串地址覆盖最高值。所以你的堆栈是:
然后printf打印这两个值。
实际上,您似乎并不需要所有的推送/弹出。唯一需要堆栈的地方是对printf的调用。必须是:
将值保存到输入(以千字节为单位使用)和输入2(以兆字节为单位使用)时, 您不需要弹出任何东西。
您可以使用:
kilobyte:
mov eax, [input]
cdq
mov ebx, 1024
idiv ebx
mov [input], eax
因此,输入现在包含idiv的结果。同样,以兆字节为单位:
megabyte:
mov eax, [input2]
cdq
mov ebx, 1048576
idiv ebx
mov [input2], eax
与前面的代码一样,现在,input2包含所需的结果。 最后,在printOut中:
printOut:
push [input2]
push [input]
push $output
call printf
祝你好运。