从x86汇编中的寄存器打印ASCII字符范围

时间:2011-08-13 03:43:39

标签: linux assembly ascii

我正在尝试使用此程序集程序打印一系列ascii字符。 我试图只使用寄存器,但没有太多运气。一切看起来都很好,但我是装配编程的新手,可能错过了一些明显的东西。任何见解将不胜感激。谢谢:)

强调文字     。文本     .global _start

_start:
 movl $1, %edx

movl $65, %ebx
start_loop:
 addl $1, %ebx 
 movl $0x04, %eax
 int $0x80
 cmpl $126, %ebx
 jle start_loop 
 jmp start_loop 

 exit
 movl $0, %ebx
 movl $1, %eax
 int $0x80

2 个答案:

答案 0 :(得分:3)

您正在调用sys_write系统调用。 sys_write()接受三个参数,输出设备的文件描述符(对于stdout应为1),存储要打印的值的缓冲区的地址,以及要打印的数据的大小。因此,您必须将文件描述符存储在%ebx中,并将缓冲区的地址存储在%ecx中,并将数据的大小存储在%edx中。要存储文件描述符,可以使用以下指令。

          movl $1, %ebx        // store 1 (stdout) in ebx)

要存储您可以使用的数据大小:

          movl $1, %edx        // size is 1 byte

现在,你必须存储缓冲区的地址,你需要把你的数据放在内存中的某些地方,并且需要在%ecx中存储内存的地址。假设您希望将数据存储在堆栈中,那么您可以这样做:

          subl $4, %esp     // get 4 bytes of memory in the stack
          movl $65, (%esp)  // store data in the memory where esp points to
          movl %esp, %ecx   // store address of the data in the ecx

现在你可以发出int 0x80。

         movl $04, %eax    // store syscall number in eax    
         int  $0x80       // issue the trap interrupt

作为一个整体,您可以编写以下代码:

    movl $1, %ebx
    subl $0x4, %esp
    movl $64, (%esp)
    start_loop:
    movl (%esp), %eax
    addl $1, %eax
    movl %eax, (%esp)
    movl %esp, %ecx
    movl $1, %edx
    movl $0x04, %eax
    int $0x80
    movl (%esp), %eax
    cmpl $126, %eax
    jle start_loop
    addl $0x4, %esp

请参阅http://www.rulingminds.com/syscallspart2上的Linux系统调用Part2,以了解有关寄存器和系统调用用法的更多信息。

答案 1 :(得分:1)

“非常感谢您提供了丰富的答案,但有没有办法存储和检索要在寄存器中打印的值而不指向它?” - 这可能已被编辑成问题。

如果你坚持只使用系统调用(int $0x80)与系统接口,那么答案是否定的。你必须以某种方式将缓冲区传递给write并且rullingminds的答案适用。

使用libc putchar(3)它是直截了当的。我使用%ebx来保存ascii代码,因为这个寄存器是在函数调用之间保留的linux上。只需使用gcc filename.S进行汇编(如果您使用的是x86_64,请记住使用-m32)。

.text

.extern putchar

.global main
main:  
    # make room for argument to putchar on the stack
    sub $4, %esp

    # initialize ebx with first value to print
    mov $'A', %ebx
1:
    # give character to print as argument
    mov %ebx, (%esp)
    call putchar

    # move to next character
    inc %ebx

    # are we done?
    cmp $'~', %ebx
    jle 1b

    # print newline
    movl $10, (%esp) 
    call putchar

    # adjust stack back to normal
    add $4, %esp

    # return 0 from main
    mov $0, %eax
    ret