我正在尝试在x86程序集中将输入字符转换为输出符号。例如,如果用户输入A
,我希望输出以下内容:
$
$ $
$$$$$
$ $
$ $
对于B
:
$$$$
$ $
$$$$
$ $
$$$$
等等。我目前的方法是设置一个0和1的字符串,然后循环并将0
转换为空间,将1
转换为$
。我使用b
作为换行符(即新行(,使用x
作为字符串的末尾。
我下面的代码(只是显示A
运行以缩短代码(:
section .data
; constants
NULL equ 0
EXIT_SUCCESS equ 0
EXIT_FAIL equ 1
SYS_exit equ 60
SYS_read equ 0
SYS_write equ 1
STD_in equ 0
STD_out equ 1
; other
text1 db "Please enter an upper-case letter from A-E: ",0
errmsg db "Error: incorrect letter chosen.",0
sucmsg db "Success.",0
symA db "00100b01010b11111b10001b10001x ",0
space db " "
dollar db "$"
lbreak db "b"
lend db "x"
section .bss
; reserve space for user input
letter resb 1
section .text
global _start
_start:
; print question
mov rax, text1
call _printText
; get user input
; sys_read (0, latter, 1)
mov rax, SYS_read
mov rdi, STD_in
mov rsi, letter
mov rdx, 1
syscall
; dereference rsi
movzx rsi, byte [letter]
; jump conditionals
mov rdx, "A"
cmp rsi, rdx
je _printA
; default jump if no match
; print fail msg
mov rax, errmsg
call _printText
jmp _exitFail
_printA:
xor eax, eax
; sys_write (1, text, 1)
mov rax, symA
call _printText
call _printChar
jmp _exitSuccess
_exitFail:
; default error exit
; sys_exit (1)
mov rax, SYS_exit
mov rdi, EXIT_FAIL
syscall
_exitSuccess:
; print success msg
mov rax, sucmsg
call _printText
; sys_exit (0)
mov rax, SYS_exit
mov rdi, EXIT_SUCCESS
syscall
; functions
_printText:
push rax
mov rbx, 0
_ptLoop:
inc rax
inc rbx
mov cl, [rax]
cmp cl, 0
jne _ptLoop
mov rax, SYS_write
mov rdi, STD_out
pop rsi
mov rdx, rbx
syscall
ret
_printChar:
;push rax
mov rbx, 0
_pcLoop:
inc rax
inc rbx
mov cl, [rax]
; if 0
cmp cl, 0
je _movSpace
; if 1
cmp cl, 1
je _movSymbol
; if newline
cmp cl, lbreak
je _movNewLine
; if end
cmp cl, lend
je _endPrint
_movSpace:
mov rcx, space
loop _pcLoop
_movSymbol:
mov rcx, dollar
loop _pcLoop
_movNewLine:
mov rcx, "n"
loop _pcLoop
_endPrint:
mov rax, SYS_write
mov rdi, STD_out
mov rsi, rcx
mov rdx, rbx
syscall
ret
目前,我已经尝试过调试,因为我在_printChar
函数中获得了Segmentation fault (core dumped)
,但是,现在有了上面的代码,我无法创建可执行文件,因为它返回以下错误:
(.text+0x10e): relocation truncated to fit: R_X86_64_8 against '.data'
(.text+0x113): relocation truncated to fit: R_X86_64_8 against '.data'
当尝试在终端中运行以下命令时:
ld filename.o -o filename
有人能对上面的代码提出一些建议来帮助实现我想要的目标吗?
我假设您使用制作程序
nasm -f elf64 filename.asm -o filename.o -l filename.lst
ld filename.o -o filename
Linker在.text+0xca
报告了一个问题,因此您需要在";filename.lst";在.text
段中的0xca
偏移处生成了什么指令:
....
112 000000C3 80F901 cmp cl, 1
113 000000C6 7416 je _movSymbol
114 ; if newline
115 000000C8 80F9[78] cmp cl, lbreak
116 000000CB 741D je _movNewLine
117 ; if end
118 000000CD 80F9[79] cmp cl, lend
119 000000D0 741F je _endPrint
....
这是cmp cl, lbreak
。查看定义lbreak db "b"
,很明显,您的指令错误地尝试将cl
中的字节值与.data
部分中变量lbreak
的偏移量进行比较,恰好是78。您可能打算将cl
与存储在内存中的值"b"
进行比较,使用cmp cl, [lbreak]
,甚至更好,使用立即值:cmp cl,"b"
。
还可以考虑使用单个_printText
:将大写字母打印为一个以0结尾的字符串
SECTION .data
BigA DB " $ ",10
DB " $ $ ",10
DB "$$$$$",10
DB "$ $",10
DB "$ $",10
DB 0
BigB DB "$$$$ ",10
DB "$ $",10
DB "$$$$ ",10
DB "$ $",10
DB "$$$$ ",10
DB 0