Gcc 套印胶印如何影响印刷
所以我有一个汇编程序,我试图通过调用printf来输出一些数据,但它不会打印我要打印的全部内容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
.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字节的空间,也可以保证零结尾,但您会输入不同长度的字符串吗?)有时,您还必须编写零终止符,以避免附加旧值)