基于英特尔的汇编语言idiv

use*_*055 2 x86 assembly

我正在努力idiv工作正常而且我已经读过你把你想要划分的东西比如25然后在ebx你把你想要划分的东西比如5然后你做

idiv ebx
Run Code Online (Sandbox Code Playgroud)

然后将EAX= 5然后EDX= 0.

但是它在我的程序中没有这样做我输入的是100000000

输出:

Kilobytes:1亿

兆字节: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
Run Code Online (Sandbox Code Playgroud)

UPDATE

好吧,我输入xor edx, edx但我仍然获得与以前相同的输出.我查看了我的电子书和其他网站,它说同样的事情,所以我真的不确定我做错了什么.也试过idiv没有运气的路线.

Lee*_*eor 5

您需要初始化 EDX - 要么将其归零 ( xor edx, edx) 并使用无符号运算,要么将 EAX 符号扩展到其中 ( cdq)


IDIV 的作用如下(链接):

将 AX、DX:AX 或 EDX:EAX 寄存器(被除数)中的值除以源操作数(除数)(有符号),并将结果存储在 AX (AH:AL)、DX:AX 或 EDX:EAX 中寄存器。源操作数可以是通用寄存器或内存位置。

该指令的动作取决于操作数的大小(dividend/divisor),如下表所示: IDIV Results [header]Operand

在此处输入图片说明

由于您除以 EBX,因此需要从 EDX:EAX 中获得红利。您没有将 EDX 初始化为零,因此得到了垃圾结果。


joh*_*und 5

关于师

首先,对于您需要的目标(计算MBytes和KBytes),您实际上需要无符号的划分.所以,用div指令代替idiv.

第二,dividiv实际分64位数目edx:eax由指定为操作数32位数字.但是你的edx寄存器包含随机数.

因此,您必须eax在分区之前将数字扩展到64位.

对于idiv使用:

    cdq       ; convert signed 32bit number in eax into signed 64bit in edx:eax
    idiv  ebx
Run Code Online (Sandbox Code Playgroud)

对于div使用:

    xor   edx, edx  ; set edx to 0 in order to extend unsigned eax in edx:eax
    div   ebx
Run Code Online (Sandbox Code Playgroud)

关于printint

您的打印代码看起来错误:

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
Run Code Online (Sandbox Code Playgroud)

首先,为什么要跳转到下一个地址?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
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到,结果存储在[input2]中,但[input]被压入堆栈.为什么?下一条指令将mov dword [esp], output覆盖堆栈中的最后一个推送值.

请注意,推送指令首先递减esp,然后将推送值存储在[esp].在这里你需要push output.