我开始深入研究装配编程;我使用NASM作为64位Debian系统的汇编程序。为了让我的脚湿透,我开始了一个基本项目 - 打印小写字母,一次打一个字母,每行一个字母。
从技术上讲,我成功实现了这一目标 - 但我不确定如何。这是我的计划:
section .data
newline: db 0x0A
outlength: db 0x00
section .bss ; variables
output: resb 1
section .text ;main function
global _start
_start:
mov word [output],0x61
_loop:
call _write
mov eax, [output]
inc eax
mov [output],eax
cmp eax, 0x7B
jne _loop;
mov eax,1
mov ebx,0
int 80h
_write:
mov eax,4
mov ebx,1
mov edx,outlength
mov ecx,newline
int 80h
ret
该程序产生以下输出:
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
这里很难显示,但在第一行之前还有一个额外的换行符,我的bash提示符会立即显示在z字符之后(在同一行)。这个输出是如何产生的? output
同时兼作要写入的字符以及循环的计数器; newline
是一个包含换行符本身的保留字节。有两个未解决的问题我无法弄清楚:
1。我的输出长度为0 - 如何打印?
2。我只是将newline
移到输出寄存器中 - 那么output
中的数据如何被使用?
答案 0 :(得分:3)
我在您的代码中看到了许多错误:
mov word [output],0x61
这是不正确的,因为您只为output
保留了一个字节的空格。请改用mov byte [output],0x61
。
mov eax, [output]
inc eax
mov [output],eax
出于同样的原因,这是不正确的。 output
是单个字节,而不是dword
。您只需使用inc byte [output]
(然后cmp byte [output],0x7B
)。
mov edx,outlength
这会将outlength
的地址放在edx
中,而不是其值(请参阅NASM Requires Square Brackets For Memory References)。
你想要movzx edx, byte [outlength]
。或者,如果您将声明从mov edx, [outlength]
更改为db
,则可以使用dd
。
现在回答你的问题:
- 我的输出长度为0 - 如何打印?
醇>
如上所述,它不是0。
- 我只是将换行符移到输出寄存器中 - 那么输出中的数据是如何使用的?
醇>
因为您将edx
设置为"随机"值,您最终可能会打印很多字符(其中一些字符可能不可见)。因此,sys_write
最终打印出您在output
存储的字符并非不可信。