无法打印NASM中堆栈上的PUSHed换行符

时间:2017-10-30 20:23:24

标签: linux assembly x86 nasm linefeed

我正在学习NASM汇编程序,而且我现在因处理换行而陷入困境。

如何打印换行符?我会给你看。但是,在我展示它之前,告诉你我的平台非常重要:

$ uname -a
Linux 4.4.0-97-generic #120-Ubuntu SMP Tue Sep 19 17:28:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID : Ubuntu
Description    : Ubuntu 16.04.3 LTS
Release        : 16.04
Codename       : xenial

我为学习准备的功能:

sprint:
    push rdx
    push rbx
    push rax
    push rcx
    mov  rax, rcx
    pop  rcx
    jmp  next_char
    ret

sprint_syscall:
    mov rbx, 1
    mov rax, 4
    int 80h
    pop rax
    pop rbx
    pop rdx
    ret

sprint_linefeed:
    call sprint
    push rcx
    mov  rcx, 0Ah
    push rcx
    mov  rcx, rsp
    call sprint
    pop  rcx
    pop  rcx
    ret

next_char:
    cmp byte [rax], 0
    jz  count_length
    inc rax
    jmp next_char

count_length:
    sub rax, rcx
    mov rdx, rax
    jmp sprint_syscall

quit:
    push rbx
    push rax
    mov  rbx, 0
    mov  rax, 1
    int  80h
    pop  rax
    pop  rbx
    ret

主应用程序,可以使用给定功能之一:

%include 'functions.asm'

SECTION .data
    msgFirst  db "Hello World!", 0h
    msgSecond db "Another string.", 0h

SECTION .text
global _start

_start:
    mov  rcx, msgFirst
    call sprint_linefeed
    mov  rcx, msgSecond
    call sprint_linefeed
    call quit

一切正在编译,也很好用。如果要编译/链接:

nasm -g -f elf64 -l main.lst main.asm -o main.o && ld main.o -o main

然后执行已编译的应用程序,我们可以看到:

Hello World!Another string

正如您所看到的那样,没有任何换行,尽管调用了sprint_linefeed函数,该函数使用下一条打印换行符的说明:

sprint_linefeed:
    call sprint
    push rcx      ; push rcx onto the stack to preserve it
    mov  rcx, 0Ah ; move 0Ah into rcx, 0Ah is the ASCII char for a linefeed
    push rcx      ; push the linefeed char onto the stack
    mov  rcx, rsp ; move the address of the pointer into rcx for the 'sys_write' syscall
    call sprint
    pop  rcx      ; remove the linefeed char from the stack
    pop  rcx      ; restore the original value of rcx
    ret

因此,对我的操作的解释是指sprint()调用给定的字符串然后将0Ah char推送到堆栈。之后,我从RSP寄存器获取指针再次调用sprint()函数。

已完成,因为SYS_WRITE系统调用需要指针来打印给定字符串(http://fresh.flatassembler.net/lscr/data/004.html)。

如果要将OAh字符添加到字符串声明:

SECTION .data
    msgFirst  db "Hello World!", 0Ah, 0h

调用相同的函数,但使用不同的字符串值,给我们等待结果,但它没有意义,因为sprint_linefeed()被定义为传递冗余ASCII-char的声明。

我应该在源代码中修复哪些内容才能使sprint_linefeed()正常工作?

1 个答案:

答案 0 :(得分:1)

@Neverlands我通过删除sprint_linefeed对您的functions.asm进行了一些小修改,并将以下内容放在文件的顶部:

%define newline 0Ah

SECTION .data
    lineEnding db newline, 0h

sprint_linefeed:
    call sprint
    mov  rcx, lineEnding
    call sprint
    ret

它可能不是你想要的,但它确实给出了:

Hello World!
Another string.

作为输出。玩得开心!