2013-11-08 6 views
2

Я пытаюсь получить idiv, работая правильно, и я прочитал, что вы положили то, что хотите разделить , например 25, а затем в ebx вы помещаете то, что хотите разделить, например, 5 выintel-Based Assembly Язык idiv

idiv ebx 

, который затем помещает EAX = 5, а затем EDX = 0.

Однако это не делает, что в моей программе вход я делаю

выход:

килобайт: 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 

UPDATE

Ну я положил в xor edx, edx, но я все еще получаю тот же результат, как и раньше. Я заглянул в свою электронную книгу и другие сайты, и она говорит то же самое, поэтому я действительно не знаю, что я делаю неправильно. Как и пробовал маршрут idiv без везения.

+0

Ничего не называется «Язык ассемблера на базе Intel». Intel имеет множество разных архитектур с соответствующим другим языком ассемблера. Вопрос должен быть тегом с 'x86' –

+0

Проверьте мой ответ о дополнительной информации о печати. – johnfound

ответ

4

Вы должны инициализировать EDX - либо обнулить его (xor edx, edx) и использовать неподписанные операции, или знак расширения EAX в него (cdq)


IDIV делает следующим образом (link):

Разделяет (подписывает) значение в AX, DX: AX или EDX: EAX регистрирует (дивиденд) операндом-источником (делителем) и сохраняет результат в AX (AH: AL), DX: AX или EDX: регистры EAX. Исходный операнд может быть регистром общего назначения или местом памяти.

Действие этого инструкции зависит от размера операнда (делимое/делитель), как показано в следующей таблице: IDIV Результаты [заголовок] Операнд

enter image description here

Поскольку вы деление на EBX, он будет получать дивиденды от EDX: EAX. Вы не инициализировали EDX до нуля, и поэтому получили результат мусора.

+0

В общем, вам нужно _sign extend_ 'eax' в' edx': обнуление 'edx' корректно, если' eax' всегда положителен. – gsg

+0

@gsg - Правильно, исправление – Leeor

+0

ОК, но я получаю те же ошибки. Оглядываясь назад на мою книгу, он использует idiv с cdq, но использует ecx вместо ebx. – user2922055

5

О разделении

На первом, для достижения цели вам нужен (Вычислительный мегабайт и кбайт) вам нужен неподписанный DeVision на самом деле. Итак, используйте инструкцию div вместо idiv.

Во-вторых, div и idiv фактически делят 64-битное число в edx:eax на 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 

О 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 

Во-первых, зачем прыгать на следующий адрес ??? Процессор пойдет сам собой. Это не совсем ошибка, но делает код менее читаемым и просто избыточным.

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], но [вставка] помещается в стек. Зачем? Следующая команда mov dword [esp], output перезаписывает последнее нажатое значение в стеке.

Обратите внимание, что команда push сначала уменьшает esp, а затем сохраняет нажатое значение в [esp]. Здесь вам нужно push output.

+0

«push dword [input]; Положите в стек« спасибо, что указали это, предположим, что input2 нажата, опечатка. Я ввел ** jmp **, потому что думал, что нужно вызвать следующую функцию, как если бы она была как функция C/C++. – user2922055