2015-06-08 46 views
1

我試圖做一個printeline函數,但是當我比較rsp地址的值時,cmp失敗。(x64 Nasm)Linux上的Writeline函數

這是通用的打印功能:

print: 
     push rdx 
     push rcx 
     push rbx 
     push rax 

call stringlen ;calls stringlen. new return address assigned to rbx 

mov rdx, rax ;move rax (containing string length) to rdx 
pop rax  ; restore original rax argument value (string address) 

mov rcx, rax ; move msg address to rcx 
mov rbx, 1 ; stdout 
mov rax, 4 ;opcode 4 print 
int 80h  ;linux interrupt 

pop rbx  ;restore original return address to rbx 
pop rcx  ; restore value of rcx 
pop rdx  ;restore value of rdx 
ret 

這裏是打印行機能的研究。它調用print來先打印消息。 然後它將換行符壓入堆棧以獲取它的地址。然後它再次打印以rax存儲的換行地址來打印它。

;prints msg with a line feed 
    printline: 
     call print ;print the message 

     push rax 
     mov rax, 0Ah ;move linefeed into rax 
     push rax ;push rax onto the stack 
     mov rax,rsp ;get the address of linefeed from rsp 
     call print ;print the linefeed 
     mov rdx, 1 
     mov rcx, rax 
     mov rbx, 1 
     mov rax, 4 
     int 80h 
     pop rax 
     pop rax 
     ret 
    ;gets string length 
    stringlen: 
     push rbx ;push return address to stack 
     mov rbx, rax ;rax holds the argument-> msg address 

我認爲這個問題是在這裏:

nextchar: ;do the counting 
     cmp byte [rax], 0h ; When comparing address from rsp, zero flag is set 

零標誌設置,並跳轉到成品,而不是公司和循環回:

 jz finished 
     inc rax 
     jmp nextchar 

    finished: 
     sub rax, rbx ;store the new argument rax as msg length 
     pop rbx ;mov return address back into rbx 
     ret ;go to return address 

這是主要的。 asm我打電話給printline:

%include "stdio.asm" 
    section .data 
    msg db "Print message 1:Hello world", 0h 

    section .text 
    global _start 

    _start: 
    mov rax, msg 
    call printline ;msg is printed but no linefeed 

    mov rax, 0 
    call return 

我已經通過gdb運行它,並且rsp和rax似乎指向正確的值(0x0a)。不確定爲什麼cmp在這裏設置零標誌。 :(

+0

爲什麼不使用repne scasb來計算字符串長度? –

+0

忽略你在調試中看到的內容,當你運行程序時會發生什麼?它打印錯誤的東西?還是會崩潰? –

回答

0

64位模式不使用int 80h,這是32位系統調用接口,如果幸運的話,它可能工作,如果指針恰好在範圍內,但不推薦使用,但堆棧通常不在。該範圍,這就是爲什麼你的代碼不能工作在print的代碼應該是這樣的:

print: 
    push rdx 
    push rcx 
    push rbx 
    push rax 

    call stringlen ; calls stringlen 

    mov rdi, 1 ; stdout 
    pop rsi  ; restore original rax argument value (string address) 
    mov rdx, rax ; move rax (containing string length) to rdx 
    mov rax, 1 ; sys_write 
    syscall 

    pop rbx  ; restore value of rbx 
    pop rcx  ; restore value of rcx 
    pop rdx  ; restore value of rdx 
    ret 

根據需要調整保存/恢復的代碼你似乎混淆了rbx,你爲什麼不停的叫喚。它「返回地址」?

PS:不知道什麼額外的sys_write裏面的printline應該這樣做。

+0

謝謝。我有點新裝配一般,並已遵循32位教程。很多這些只是我爲了幫助我理解正在發生的事情而發表的評論。至於rbx,我認爲當函數被調用時,它是存儲返回地址的地方。如果情況並非如此,我會糾正它。 – helloworld4890

+0

返回地址存儲在堆棧中,不涉及'rbx'。 – Jester