简体   繁体   English

NASM一次打印一个字符

[英]NASM Print one Character at a Time

How come this program is not printing out to the screen, am I missing something on the INT 80 command? 为什么该程序没有打印到屏幕上,我是否在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                         ;

ADDITION 加成

My Makefile: 我的Makefile:

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

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

Modified Code: 修改后的代码:

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                         ;   

One of the reasons it's not printing is because ebx is supposed to hold the value 1 to specify stdin , and another is because sys_write takes a pointer (the address of your string) as an argument, not an actual character value. 它不打印的原因之一是因为ebx应该保留值1来指定stdin ,而另一个原因是sys_write将指针(字符串的地址)作为参数,而不是实际的字符值。

Anyway, let me show you a simpler way of structuring your program: 无论如何,让我向您展示一种简化程序结构的方法:

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

It can be simpler to NUL terminate your string as I did, or you could also do $-hello to get it's length at compile time. 像我一样,用NUL终止字符串可能更简单,也可以执行$-hello来在编译时获取其长度。 I also set the registers up for sys_write at each iteration in the loop (as you do), since sys_write doesn't preserve all the registers. 我还会在循环的每次迭代中为sys_write设置寄存器(如您sys_write ),因为sys_write不会保留所有寄存器。

I don't know how you got your code to assemble, but it doesn't assemble over here for a couple of very good reasons. 我不知道如何汇编代码,但是由于一些非常好的原因,它没有在这里汇编。

You cannot use loop as a label name because that name is reserved for the loop instruction. 您不能将loop用作标签名称,因为该名称是为loop指令保留的。

Your line 20's instruction mov ecx, byte [hello + ebx] doesn't assemble either because the source and destination operands' sizes don't match (byte vs dword). 您的第20行的指令mov ecx, byte [hello + ebx]也不汇编,因为源和目标操作数的大小不匹配(字节与dword)。 Possible changes: 可能的变化:

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

Was the above not the actual code you had? 以上不是您的实际代码吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM