Gcc 套印胶印如何影响印刷

Gcc 套印胶印如何影响印刷,gcc,assembly,x86-64,Gcc,Assembly,X86 64,所以我有一个汇编程序,我试图通过调用printf来输出一些数据,但它不会打印我要打印的全部内容 .section .data output: .asciz "The processor Vendor ID is ‘%s’\n" .section .bss .lcomm buffer, 64 .section .text .globl _start _start: pushq %rbx

所以我有一个汇编程序,我试图通过调用printf来输出一些数据,但它不会打印我要打印的全部内容

    .section .data
    output:
            .asciz "The processor Vendor ID is ‘%s’\n"

    .section .bss
    .lcomm buffer, 64
    .section .text

    .globl _start
    _start:
            pushq %rbx
            movq $0, %rax
            cpuid

            movq $buffer, %rsi
            movq $output, %rdi
            mov %ebx, 28(%rdi)
            mov %ecx, 32(%rdi)
            #mov %edx, 35(%rdi)

            movq $0, %rax
            call printf

            movq $60, %rax
            movq $0, %rdi
            popq %rbx
            syscall
然而,这个版本完全不打印任何内容;此版本:

    .section .data
    output:
            .asciz "The processor Vendor ID is ‘%s’\n"

    .section .bss
    .lcomm buffer, 64
    .section .text

    .globl _start
    _start:
            pushq %rbx
            movq $0, %rax
            cpuid

            movq $buffer, %rsi
            movq $output, %rdi
            mov %ebx, 27(%rdi)
            mov %ecx, 31(%rdi)
            #mov %edx, 35(%rdi)

            movq $0, %rax
            call printf

            movq $60, %rax
            movq $0, %rdi
            popq %rbx
            syscall
此版本打印出
处理器供应商ID为Genuntel
,即使偏移量只更改了一个。如果我包含注释行,无论发生什么,程序都不会打印任何内容(在第一个示例中,我知道偏移量是错误的,但即使它是36,也不会打印)。因此,我很好奇偏移量是如何影响它的,这样它就不会打印第一个,而是打印第二个


请记住,这是一项学校作业,但我已经尝试了好几天了,似乎无法让它发挥作用

此代码看起来是为您设置的,用于将字符串字节存储到相对于RSI的
缓冲区中,因此格式字符串中的
%s
转换将打印它。但是使用
.data
中的字符串而不是
.rodata
中应该放置只读数据的位置,可以在运行时覆盖格式字符串的字节

覆盖
\n
时,
printf
不会刷新输出缓冲区,因为
stdout
是行缓冲的。使用
sys\u exit
(直接系统调用)退出,而不是
call exit
或从
main
返回,使数据未打印。看


您可以使用
ltrace./my_程序
查看它进行的库函数调用。

因此,我假设您试图告诉我的是,我应该用整个字符串替换“%s”,而不是将字节强制放入缓冲区?我该怎么做呢?我理解原因,现在我想知道如何修复它。不,你应该
mov%ebx,(%rsi)
所以你最终调用
printf(“废话废话'%s'\n”,“GenuineIntel”)而不是将格式字符串重写为
printf(“废话废话”GenuineIntel),未使用的参数。类似于
printf
而不是
put
的函数的全部要点是,在调用它之后,它将替换为格式字符串。或者,您可以在字符串末尾留出额外的空间来存储内容,然后调用
put
,而不是
printf
。(请注意,
put
隐式地添加了一个换行符。)无论如何,您应该从main中
ret
,而不是退出
syscall
,或者使用
sys\u write
。在这两个代码示例中,您将数据存储到
输出中,覆盖它(在调试器中观察内存的这一部分,会发生什么),而您在其他地方保留了
缓冲区
内存,这些内存也可以使用(但作为
printf
的第二个参数,它应该是以零结尾的字符串。
.bss
部分在输入
main
时被置零,因此写入
cpuid
供应商字符串一次,并至少保留+1字节的空间,也可以保证零结尾,但您会输入不同长度的字符串吗?)有时,您还必须编写零终止符,以避免附加旧值)