簡體   English   中英

NASM一次打印一個字符

[英]NASM Print one Character at a Time

為什么該程序沒有打印到屏幕上,我是否在INT 80命令上缺少某些內容?

  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                         ;

加成

我的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                         ;   

它不打印的原因之一是因為ebx應該保留值1來指定stdin ,而另一個原因是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

像我一樣,用NUL終止字符串可能更簡單,也可以執行$-hello來在編譯時獲取其長度。 我還會在循環的每次迭代中為sys_write設置寄存器(如您sys_write ),因為sys_write不會保留所有寄存器。

我不知道如何匯編代碼,但是由於一些非常好的原因,它沒有在這里匯編。

您不能將loop用作標簽名稱,因為該名稱是為loop指令保留的。

您的第20行的指令mov ecx, byte [hello + ebx]也不匯編,因為源和目標操作數的大小不匹配(字節與dword)。 可能的變化:

mov cl,字節[hello + ebx]
mov ecx,dword [hello + ebx]
movzx ecx,字節[hello + ebx]

以上不是您的實際代碼嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM