2012-06-29 42 views
1

爲了讓您在寄存器上執行整數/浮點除法操作,我一直在讀取該值,因此需要實際執行的寄存器爲initialized。我很好奇正確的彙編指令是做什麼的。我是否只是通過類似提供地址:將兩個值相乘並將它們打印到屏幕上(NASM,Linux)

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' 
+0

請詳細解釋您要完成的工作。是的,內存/和或寄存器必須設置爲有效值,以便指令執行任何有意義的操作 - 這與高級語言中的變量沒有區別。你的第一條指令簡單地將ecx寄存器設置爲0x65f,第二條指令將ecx指向的0xa字節存儲起來。 –

+0

更新;我很感謝幫助。 – zeboidlund

+2

請參閱:http://stackoverflow.com/questions/9793060/getting-floating-point-exception-while-trying-to-use-div-in-assembly在發出'div'之前,您需要將'edx'歸零,指令。 – Mysticial

回答

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) 
; 
; 

尾翼警報...

它打印出結果BACKWARDS!
爲了解決這個問題,我們必須重新設計如何獲得數字 並在打印前存儲。

我通過電子郵件直接向您發送此消息以及其他一些注意事項。

+0

謝謝,lornix。我在der gdb學習。 – zeboidlund

相關問題