linux - 无法打印在 NASM 堆栈上推送的换行符

标签 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

然后执行编译好的app,我们可以看到:

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 字符压入堆栈。稍后,我从 RSP 寄存器获取指针以再次调用 sprint() 函数。

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

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

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

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

我应该在我的源代码中修复什么才能使 sprint_linefeed() 正常工作?

最佳答案

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

作为输出。玩得开心!

关于linux - 无法打印在 NASM 堆栈上推送的换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47023590/

相关文章:

x86 - hyperledger sawtooth Lake——是否仅限英特尔?

java - 如何将调用的命令/程序的输出重定向到 log4j?

assembly - 如何设置寄存器CR0的MP和TS标志? x86 法斯姆

assembly - 如何在 x86 程序集中设置或清除溢出标志?

if-statement - FASM - x64 与 x86

c# - 由于格式不正确,加载程序集失败

c++ - 我可以在其中存储数据的地方/C++,Linux,QtCreator

命令行 * linux

ruby-on-rails - 在 bash 中执行 rake 命令

assembly - 编译汇编语言