2011-12-08 13 views
2

どうすればこのプログラムが画面に表示されないのですか?INT 80コマンドで何かが見つからないのですか?NASM一度に1文字を印刷する

section .bss 

    section .data 
     hello: db "Hello World",0xa  ;10 is EOL 

    section .text 
     global _start 

    _start: 

     mov ecx, 0;      ; int i = 0; 
    loop: 
     mov dl, byte [hello + ecx]  ; while(data[i] != EOF) { 
     cmp dl, 0xa      ; 
     je exit       ; 
     mov ebx, ecx      ; store conetents of i (ecx) 

     ; Print single character 
     mov eax, 4      ; set sys_write syscall 
     mov ecx, byte [hello + ebx]  ; ... 
     mov edx, 1      ; move one byte at a time 
     int 0x80       ; 

     inc ebx       ; i++ 
     mov ecx, ebx      ; move ebx back to ecx 
     jmp loop       ; 

    exit: 
     mov eax, 0x01     ; 0x01 = syscall for exit 
     int 0x80       ; 

ADDITION

私のMakefile:

sandbox: sandbox.o 
    ld -o sandbox sandbox.o 

sandbox.o: sandbox.asm 
    nasm -f elf -g -F stabs sandbox.asm -l sandbox.lst 

修正コード:

section .bss 

section .data 
    hello: db "Hello World",0xa  ;10 is EOL 

section .text 
    global _start 

_start: 

    mov ecx, 0;      ; int i = 0; 
while: 
    mov dl, byte [hello + ecx]  ; while(data[i] != EOF) { 
    cmp dl, 0xa      ; 
    je exit       ; 
    mov ebx, ecx      ; store conetents of i (ecx) 

    ; Print single character 
    mov eax, 4      ; set sys_write syscall 
    mov cl, byte [hello + ebx]  ; ... 
    mov edx, 1      ; move one byte at a time 
    int 0x80       ; 

    inc ebx       ; i++ 
    mov ecx, ebx      ; move ebx back to ecx 
    jmp while      ; 

exit:  
    mov eax, 0x01     ; 0x01 = syscall for exit 
    int 0x80       ; 
+0

あなたが編集で言及したその追加文字に関する私のコメントを読んでください。 – AusCBloke

答えて

5

ebxstdinを指定するには、値1を保持することになって、そしてsys_writeは、引数ではなく、実際の文字値としてポインタ(あなたの文字列のアドレス)を要するため、別のがあるされているので、それは印刷していない理由の一つです。とにかく

、私はあなたのプログラムを構築する簡単な方法を示してみましょう:

section .data 

    SYS_EXIT equ 1 
    SYS_WRITE equ 4 
    STDOUT equ 1 
    TRAP  equ 0x80 
    NUL  equ 0 

    hello: db "Hello World",0xA,NUL ; 0xA is linefeed, terminate with NUL 

section .text 
    global _start 

_start: 
    nop      ; for good old gdb 
    mov ecx, hello   ; ecx is the char* to be passed to sys_write 

read: 
    cmp byte[ecx], NUL  ; NUL indicates the end of the string 
    je exit     ; if reached the NUL terminator, exit 

    ; setup the registers for a sys_write call 
    mov eax, SYS_WRITE  ; syscall number for sys_write 
    mov ebx, STDOUT   ; print to stdout 
    mov edx, 1    ; write 1 char at a time 
    int TRAP;    ; execute the syscall 

    inc ecx     ; increment the pointer to the next char 
    jmp read    ; loop back to read 

exit:  
mov eax, SYS_EXIT  ; load the syscall number for sys_exit 
mov ebx, 0    ; return a code of 0 
int TRAP    ; execute the syscall 

私がやったか、またそれは、コンパイル時の長さです取得する$-helloを行うことができて、あなたの文字列を終了NULに簡単になることができます時間。 sys_writeはすべてのレジスタを保持していないので、ループ内の各繰り返しでレジスタを設定します(これと同じように)。

+0

@MatthewHoggan:その追加文字は意図的に印刷されています。文字列の末尾に新しい行を、文字列の最後を示す値0(NUL)を表示することは理にかなっています。余分な値を必要としない場合は、 'hello'の最後から' 0xA'を削除しますが、値 '0xA'を文字列終了値として使用しないでください。 – AusCBloke

+1

すべてのキャラクターにシステムコールを行うのは無駄でしょうか?ループ内の長さを決定し、バッファをsys_writeに一度に渡したいとは思わないでしょうか? – Thilo

0

あなたのコードをどのようにして組み立てるのか分かりませんが、ここではいくつかの理由で組み立てません。

loop命令用に予約されているため、loopはラベル名として使用できません。

ライン20の命令mov ecx, byte [hello + ebx]は、ソースオペランドとデスティネーションオペランドのサイズが一致しないため(バイトとワードの両方)アセンブルされません。可能な変更:

楽章のcl、バイト[ハロー+ EBX]
MOV ECX、DWORD [ハロー+ EBX]
movzx ECX、バイト[ハロー+ EBX]

は、実際の上記ではなかったですあなたが持っていたコード?

+0

私はFC15を利用していますが、上記のファイルを貼り付けています。変更を加えても、端末で印刷するものはまだ得られません。 –

+1

"sys_write()"は実際のデータではなくデータのアドレスを要求していると仮定します(例: "lea ecx、[hello + ebx]")。 – Brendan

関連する問題