1

我一直在阅读,为了让人们在寄存器上执行整数/浮点除法,正在执行的寄存器实际上需要是initialized. 我很好奇正确的汇编指令是做什么的。我是否只是通过以下方式提供地址:

mov ecx, 0x65F ;0x65F represents an address for ecx to point to.

然后立即(稍后在代码中)执行以下操作:

mov byte [ecx], 0xA ;move the value of 0xA into the contents of ecx, using only a byte's worth of data

这是执行此类操作的正确方法吗?如果不是,那是什么?

更新

好的,所以我要做的基本上是将两个值相乘并将它们打印到屏幕上。代码如下,由于某种原因,每次我尝试除法时edx都会遇到分段错误或浮点算术异常。有人可以向我解释我做错了什么吗?

代码

section .data
    counter: db 0xA                         ;store value 10 in 'counter', while allocating only one byte. This will be used for decrementing purposes
section .bss
    valueToPrint: resb 4                    ;alloc 4 bytes of data in 'valueToPrint'

section .text

global _start

_print_char:                    
    add eax, '0'                ;convert to ascii
    mov [valueToPrint], eax     ;store contents of 'eax' in valueToPrint
    mov eax, 4                  ;syswrite
    mov ebx, 1                  ;stdout
    mov ecx, valueToPrint       ;machine will take whatever value exists in 'ecx' and print
    mov edx, 1                  ;print only a single byte's worth of data
    int 0x80                    ;invoke kernel to perfrom instruction
    ret                         

_convert_values:
    mov edx, 0xA                ;dividing eax by 10, which will lower its tens place
    div edx                     ;(**Program crash here**)do division: remainder SHOULD be stored in edx
    mov byte [edx], 0x0         ;zero out edx       
    call _print_char            ;do printing for latest character
    dec byte [counter]          ;decrement counter
    mov dword [eax], counter    ;store counter in eax
    jnz _convert_values         ;while eax > 0 continue process

_endl:
    mov eax, '\n'               ;store newline character in eax to be printed
    call _print_char            ;print value
    ret                 

_mul:
    mov eax, 0x2A ;store 42 in eax
    mov edx, 0x2B ;store 43 in edx
    mul edx       ;multiply [eax] * [edx]
    ret

_safe_exit:
    mov eax, 1  ;initiate 'exit' syscall
    mov ebx, 0  ;exit with error code 0
    int 0x80    ;invoke kernel to do its bidding 

_start:
    nop                             ;used to keep gdb from complaining

    call _mul                       ;multiply the values
    call _convert_values            ;do hex to ascii conversion

    jmp _safe_exit                  ;use jmp as opposed to call since it technically doesn't 'ret'
4

1 回答 1

4

我们分别在聊天中交谈......

这是一个可以使用的工作版本。

它有一个微妙的问题。你能找到吗?你能解释一下为什么它会这样做吗?

; Multiply two numbers, display in ascii/decimal
;
; (because I have a 64bit system, this forces 32bit code)
        bits    32
;
        section .text
;
; _start is the ONLY label you MUST prepend _
; others might be library functions (ex: _printf,_exit)
; pure assembly only needs _start, if linked with glibc
; typically need _main INSTEAD of _start
;
        global _start
;
;
_start:
        nop                             ;placeholder for gdb's debug interrupt
;
        call    mul                     ;multiply the values
        call    convert_values          ;do hex to ascii conversion
;
        jmp     safe_exit               ;use jmp as opposed to call since it technically doesn't 'ret'
;
;
; subroutines / functions follow
;
mul:
        mov     eax, 0x2A               ;store 42 in eax
        mov     edx, 0x2B               ;store 43 in edx (42*43=1806)
        mul     edx                     ;multiply eax*edx, result in edx:eax
        ret
;
; this routine doesn't handle BIG values from 'mul' which extend into edx
; we're learning, don't make things multiply out to more than 4.2 billion-ish
convert_values:
        mov     edx,0                   ;value actually edx:eax, zero edx
        mov     ecx,0x0A                ;divide edx:eax by 10
        idiv    ecx                     ;result in eax, remainder in edx
        push    eax                     ;save value on stack
        mov     eax,edx                 ;put remainder (0-9) in eax
        add     eax,'0'                 ;convert value to ascii character
        call    print_char              ;print the latest character
        pop     eax                     ;restore value
        or      eax,eax                 ;set flags based on eax value
        jnz     convert_values          ;while eax != 0 continue process
;
; nasm doesn't convert \n into LF... just use 10, equivalent
endl:
        mov     eax, 10                 ;store newline character in eax to be printed
        call    print_char              ;print value
        ret
;
print_char:
        mov     [valueToPrint], eax     ;store contents of 'eax' in [valueToPrint]
        mov     eax, 4                  ;syswrite
        mov     ebx, 1                  ;stdout
        mov     ecx, valueToPrint       ;machine will take whatever value exists in [ecx] and print
        mov     edx, 1                  ;print only a single byte's worth of data
        int     0x80                    ;invoke kernel to perfrom instruction
        ret
;
safe_exit:
        mov     eax,1                   ;initiate 'exit' syscall
        mov     ebx,0                   ;exit with error code 0
        int     0x80                    ;invoke kernel to do its bidding
;
; =====================================
        section .bss
; this section is not allocated, just reserved.
; Automatically set to zero when program starts
;
; alloc 4 bytes of data in 'valueToPrint'
valueToPrint:
        resd    1               ; 1 resd=4 resb (Dword/Byte)
;
;

剧透警报...

它会向后打印结果!
为了解决这个问题,我们必须重新设计在打印之前如何获取和存储数字。

我将通过电子邮件将其直接发送给您,并附上一些附加说明。

于 2012-07-01T13:23:45.097 回答