简体   繁体   English

linux nasm打印多个字符

[英]linux nasm print multiple characters

I am trying to write a program that will allow me to print multiple characters (strings of characters or integers). 我正在尝试编写一个程序,允许我打印多个字符(字符串或整数)。 The problem that I am having is that my code only prints one of the characters, and then newlines and stays in an infinite loop. 我遇到的问题是我的代码只打印其中一个字符,然后换行并保持无限循环。 Here is my code: 这是我的代码:

SECTION .data
len EQU 32
SECTION .bss
num resb len
output resb len

SECTION .text
GLOBAL _start
_start:
Read:
    mov eax, 3
    mov ebx, 1
    mov ecx, num
    mov edx, len
    int 80h

Point:
    mov ecx, num

Print:
    mov al, [ecx]
    inc ecx
    mov [output], al

    mov eax, 4
    mov ebx, 1
    mov ecx, output
    mov edx, len
    int 80h

    cmp al, 0
    jz Exit

Clear:
    mov eax, 0
    mov [output], eax
    jmp Print  

Exit:
    mov eax, 1
    mov ebx, 0
    int 80h 

Could someone point out what I am doing wrong? 有人能指出我做错了什么吗?

Thanks, 谢谢,

Rileyh Rileyh

In the first time you enter the Print section, ecx is pointing to the start of the string and you use it to copy a single character to the start of the output string. 在第一次进入“ Print部分时, ecx指向字符串的开头,并使用它将单个字符复制到输出字符串的开头。 But a few more instructions down, you overwrite ecx with the pointer to the output string, and never restore it, therefore you never manage to copy and print the rest of the string. 但是更多的指令,你用指向输出字符串的指针覆盖ecx ,并且永远不会恢复它,因此你永远不会复制并打印其余的字符串。

Also, why are you calling write() with a single character string with the aim to loop over it to print the entire string? 另外,为什么用一个字符串调用write() ,目的是遍历它以打印整个字符串? Why not just pass num directly in instead of copying a single character to output and passing that? 为什么不直接传入num而不是复制单个字符来output和传递?

In your last question, you showed message as a zero-terminated string, so cmp al, 0 would indicate the end of the string. 在上一个问题中,您将message显示为以零结尾的字符串,因此cmp al, 0将指示字符串的结尾。 sys_read does NOT create a zero-terminated string! sys_read不会创建以零结尾的字符串! (we can stuff a zero in there if we need it - eg as a filename for sys_open) sys_read will read a maximum of edx characters. (如果我们需要它,我们可以填充零 - 例如作为sys_open的文件名)sys_read将读取最大的edx字符。 sys_read from stdin returns when, and only when, the "enter" key is hit. 来自stdin的sys_read返回当且仅当命中“enter”键时。 If fewer than edx characters were entered, the string is terminated with a linefeed character (10 decimal or 0xA or 0Ah hex) - you could look for that... But, if the pesky user types more than edx characters, only edx characters go into your buffer, the "excess" remains in the OS's buffer (and can cause trouble later!). 如果输入的字符少于edx字符,则字符串以换行符(10位十进制或0xA或0Ah十六进制)终止 - 您可以查找...但是,如果讨厌的用户键入的字符多于edx字符,则只有edx字符进入缓冲区后,“多余”仍留在操作系统的缓冲区中(以后可能会引起麻烦!)。 In this case your string is NOT terminated with a linefeed, so looking for it will fail. 在这种情况下,您的字符串不会以换行符结束,因此查找它将失败。 sys_read returns the number of characters actually read - up to edx - including the linefeed - in eax. sys_read返回实际读取的字符数 - 最多为edx - 包括换行符 - 在eax中。 If you don't want to include the linefeed in the length, you can decrement eax. 如果您不想在长度中包含换行符,则可以减少eax。

As an experiment, do a sys_read with some small number (say 4) in edx, then exit the program. 作为一个实验,在edx中执行一个带有少量(例如4)的sys_read,然后退出程序。 Type "abcdls"(enter) and watch the "ls" be executed. 输入“abcdls”(输入)并观察“ls”的执行情况。 If some joker typed "abcdrm -rf ."... well, don't!!! 如果有些小丑输入“abcdrm -rf。”......好吧,不要!

Safest thing is to flush the OS's input buffer. 最安全的是刷新操作系统的输入缓冲区。

  mov ecx, num mov edx, len mov ebx, 1 mov eax, 3 int 80h cmp byte [ecx + eax - 1], 10 ; got linefeed? push eax ; save read length - doesn't alter flags je good flush: mov ecx, dummy_buf mov edx, 1 mov ebx, 1 mov eax, 3 int 80h cmp byte [ecx], 10 jne flush good: pop eax ; restore length from first sys_read 

Instead of defining dummy_buf in .bss (or .data), we could put it on the stack - trying to keep it simple here. 我们不是在.bss(或.data)中定义dummy_buf ,而是将它放在堆栈上 - 试图在这里保持简单。 This is imperfect - we don't know if our string is linefeed-terminated or not, and we don't check for error (unlikely reading from stdin). 这是不完美的 - 我们不知道我们的字符串是否被换行终止,并且我们不检查错误(不太可能从stdin读取)。 You'll find you're writing much more code dealing with errors and "idiot user" input than "doing the work". 你会发现你正在编写更多代码来处理错误和“白痴用户”输入,而不是“做工作”。 Inevitable! 必然! (it's a low-level language - we've gotta tell the CPU Every Single Thing!) (这是一种低级语言 - 我们必须告诉CPU每一件事!)

sys_write doesn't know about zero-terminated strings, either! sys_write也不知道零终止字符串! It'll print edx characters, regardless of how much garbage that might be. 无论可能有多少垃圾,它都会打印edx字符。 You want to figure out how many characters you actually want to print, and put that in edx (that's why I saved/restored the original length above). 你想弄清楚你真正想要打印多少个字符,并把它放在edx中(这就是为什么我保存/恢复上面的原始长度)。

You mention "integers" and use num as a variable name. 你提到“整数”并使用num作为变量名。 Neither of these functions know about "numbers" except as ascii codes. 除了ascii代码之外,这些函数都不知道“数字”。 You're reading and writing characters. 你在读和写字。 Converting a single-digit number to and from a character is easy - add or subtract '0' (48 decimal or 30h). 将一位数字转换为字符和从字符转换很容易 - 加或减'0'(48位小数或30小时)。 Multiple digits are more complicated - look around for an example, if that's what you need. 多位数字更复杂 - 如果您需要,请查看示例。

Best, Frank 最好,弗兰克

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM