NASM一次打印一个字符 [英] NASM Print one Character at a Time

查看:175
本文介绍了NASM一次打印一个字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该程序为什么不打印到屏幕上,我是否在INT 80命令上缺少某些内容?

How come this program is not printing out to the screen, am I missing something on the INT 80 command?

  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占用了指针(字符串的地址)作为参数,而不是实际的字符值.

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.

无论如何,让我向您展示一种简化程序结构的方法:

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

像我一样,用NUL终止字符串可能更简单,或者您也可以执行$-hello以在编译时获取其长度.我还会在循环中的每次迭代中为sys_write设置寄存器(如您所愿),因为sys_write不会保留所有寄存器.

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. 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.

这篇关于NASM一次打印一个字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆