Linux 如何在汇编语言的新行上打印多个字符串

Linux 如何在汇编语言的新行上打印多个字符串,linux,assembly,x86,Linux,Assembly,X86,我试图在汇编中的不同行上打印多个字符串,但在我的代码中,它只打印最后一个字符串。我对汇编语言很陌生,所以请耐心听我说 section .text global _start _start: mov edx, len mov edx, len1 mov edx, len2

我试图在汇编中的不同行上打印多个字符串,但在我的代码中,它只打印最后一个字符串。我对汇编语言很陌生,所以请耐心听我说

 section .text             
                           
 global _start             
 _start:                    
  mov edx, len              
  mov edx, len1             
  mov edx, len2             
  mov edx, len3             
  mov ecx, msg              
  mov ecx, str1             
  mov ecx, str2             
  mov ecx, str3             
  mov ebx, 1                
  mov eax, 4                
  int 0x80                  
  mov eax, 1                
  int 0x80                  

   
  section .data             


 msg  db 'Hello, world!',0xa                       
 str1 db 'Learning is fun!',0xa 
 str2 db 'I love beacon!',0xa         
 str3 db 'I love programming',0xa                      
 len1 equ $ - str1           
 len2 equ $ - str2           
 len3 equ $ - str3           
 len  equ $ - msg            
它只打印出来我喜欢编程

它应该打印出来

 Hello World!
 Learning is fun!
 I love beacon!
 I love programming
你期待什么

您正在覆盖寄存器
edx

这与其他编程语言中的以下代码类似:

variableEdx = len;
variableEdx = len1;
第二行将覆盖变量
variableEdx
,第一行的效果将消失

如何打印多个字符串

函数
eax=4
将内存中的一些数据从某个地址开始,到某个设备的某个地址结束

如果第二个字符串紧跟在内存中的第一个字符串之后,则可以将由两个字符串组成的内存发送到设备

例如:

...
mov edx, str1
mov ecx, 32
...
.text
.globl _start

_start:
    mov edx, 3
    mov ecx, offset list
    mov ebx, 1
    mov eax, 146
    int 0x80
    mov eax, 1
    int 0x80

.data

list:
    .long msg
    .long 7
    .long str1
    .long 8
    .long str3
    .long 19

    ...
这将从
str1
开始向设备发送32字节的内存内容。从
str1
开始的32个字节是字符串
str1
str2

如果要向设备发送多个内存块,可以使用
writev()
系统调用,即function
eax=146
。(见附件)

例如:

...
mov edx, str1
mov ecx, 32
...
.text
.globl _start

_start:
    mov edx, 3
    mov ecx, offset list
    mov ebx, 1
    mov eax, 146
    int 0x80
    mov eax, 1
    int 0x80

.data

list:
    .long msg
    .long 7
    .long str1
    .long 8
    .long str3
    .long 19

    ...
不幸的是,我使用的汇编程序的语法与您的略有不同;但是,在部件中,
列表
零件可能如下所示:

list dd msg
     dd 7
     dd str1
     ...
writev
(函数146)获取指向
ecx
寄存器中某个“列表”的指针以及
edx
寄存器中列表中的条目数

列表中的每个条目由两个32位字组成。第一个字是要写入设备的存储器的地址;第二个字是要写入的字节数

上面的例子写着“你好,学习我喜欢编程”:


“msg”的前7个字节,然后是“str1”的前8个字节,然后是“str3”的所有19个字节。

int 0x80
调用内核,在这一点上,它指出您想要从EAX调用哪个系统,并在其他regs中使用args。您只需执行
write
系统调用,并浪费大量指令覆盖之前具有不同值的寄存器。使用调试器单步执行并查看寄存器值的变化,并使用
strace./my_program
跟踪系统调用。此外,除了实际使用的
len3
之外,所有长度都是错误的。(/)例如,
len
是所有字符串组合的整个长度,因此您当然可以使用一个write syscall打印整个ASCII文本块。@PeterCordes我不明白在这里该怎么做可能是重复的,或者可能是使用多个
int 0x80
指令进行多个
write
系统调用,或者将指向
msg
的指针和整个文本块的长度传递给一个
write
系统调用。内核只能在运行
int 0x80
时看到寄存器中的值,而不能看到在调用内核之前覆盖该寄存器4次的历史记录。EAX=146是
writev
系统调用;您应将其命名并链接到手册页: