[英]NASM Print one Character at a Time
How come this program is not printing out to the screen, am I missing something on the INT 80 command? 为什么该程序没有打印到屏幕上,我是否在INT 80命令上缺少某些内容?
section .bss
section .data
hello: db "Hello World",0xa ;10 is EOL
section .text
global _start
_start:
mov ecx, 0; ; int i = 0;
loop:
mov dl, byte [hello + ecx] ; while(data[i] != EOF) {
cmp dl, 0xa ;
je exit ;
mov ebx, ecx ; store conetents of i (ecx)
; Print single character
mov eax, 4 ; set sys_write syscall
mov ecx, byte [hello + ebx] ; ...
mov edx, 1 ; move one byte at a time
int 0x80 ;
inc ebx ; i++
mov ecx, ebx ; move ebx back to ecx
jmp loop ;
exit:
mov eax, 0x01 ; 0x01 = syscall for exit
int 0x80 ;
ADDITION 加成
My Makefile: 我的Makefile:
sandbox: sandbox.o
ld -o sandbox sandbox.o
sandbox.o: sandbox.asm
nasm -f elf -g -F stabs sandbox.asm -l sandbox.lst
Modified Code: 修改后的代码:
section .bss
section .data
hello: db "Hello World",0xa ;10 is EOL
section .text
global _start
_start:
mov ecx, 0; ; int i = 0;
while:
mov dl, byte [hello + ecx] ; while(data[i] != EOF) {
cmp dl, 0xa ;
je exit ;
mov ebx, ecx ; store conetents of i (ecx)
; Print single character
mov eax, 4 ; set sys_write syscall
mov cl, byte [hello + ebx] ; ...
mov edx, 1 ; move one byte at a time
int 0x80 ;
inc ebx ; i++
mov ecx, ebx ; move ebx back to ecx
jmp while ;
exit:
mov eax, 0x01 ; 0x01 = syscall for exit
int 0x80 ;
One of the reasons it's not printing is because ebx
is supposed to hold the value 1 to specify stdin
, and another is because sys_write
takes a pointer (the address of your string) as an argument, not an actual character value. 它不打印的原因之一是因为
ebx
应该保留值1来指定stdin
,而另一个原因是sys_write
将指针(字符串的地址)作为参数,而不是实际的字符值。
Anyway, let me show you a simpler way of structuring your program: 无论如何,让我向您展示一种简化程序结构的方法:
section .data
SYS_EXIT equ 1
SYS_WRITE equ 4
STDOUT equ 1
TRAP equ 0x80
NUL equ 0
hello: db "Hello World",0xA,NUL ; 0xA is linefeed, terminate with NUL
section .text
global _start
_start:
nop ; for good old gdb
mov ecx, hello ; ecx is the char* to be passed to sys_write
read:
cmp byte[ecx], NUL ; NUL indicates the end of the string
je exit ; if reached the NUL terminator, exit
; setup the registers for a sys_write call
mov eax, SYS_WRITE ; syscall number for sys_write
mov ebx, STDOUT ; print to stdout
mov edx, 1 ; write 1 char at a time
int TRAP; ; execute the syscall
inc ecx ; increment the pointer to the next char
jmp read ; loop back to read
exit:
mov eax, SYS_EXIT ; load the syscall number for sys_exit
mov ebx, 0 ; return a code of 0
int TRAP ; execute the syscall
It can be simpler to NUL terminate your string as I did, or you could also do $-hello
to get it's length at compile time. 像我一样,用NUL终止字符串可能更简单,也可以执行
$-hello
来在编译时获取其长度。 I also set the registers up for sys_write
at each iteration in the loop (as you do), since sys_write
doesn't preserve all the registers. 我还会在循环的每次迭代中为
sys_write
设置寄存器(如您sys_write
),因为sys_write
不会保留所有寄存器。
I don't know how you got your code to assemble, but it doesn't assemble over here for a couple of very good reasons. 我不知道如何汇编代码,但是由于一些非常好的原因,它没有在这里汇编。
You cannot use loop
as a label name because that name is reserved for the loop
instruction. 您不能将
loop
用作标签名称,因为该名称是为loop
指令保留的。
Your line 20's instruction mov ecx, byte [hello + ebx]
doesn't assemble either because the source and destination operands' sizes don't match (byte vs dword). 您的第20行的指令
mov ecx, byte [hello + ebx]
也不汇编,因为源和目标操作数的大小不匹配(字节与dword)。 Possible changes: 可能的变化:
mov cl, byte [hello + ebx] mov cl,字节[hello + ebx]
mov ecx, dword [hello + ebx] mov ecx,dword [hello + ebx]
movzx ecx, byte [hello + ebx] movzx ecx,字节[hello + ebx]
Was the above not the actual code you had? 以上不是您的实际代码吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.