我有一个非常简单的程序如下: #include
int main(){
char* mystring = "ABCDEFGHIJKLMNO";
puts(mystring);
char otherstring[15];
otherstring[0] = 'a';
otherstring[1] = 'b';
otherstring[2] = 'c';
otherstring[3] = 'd';
otherstring[4] = 'e';
otherstring[5] = 'f';
otherstring[6] = 'g';
otherstring[7] = 'h';
otherstring[8] = 'i';
otherstring[9] = 'j';
otherstring[10] = 'k';
otherstring[11] = 'l';
otherstring[12] = 'm';
otherstring[13] = 'n';
otherstring[14] = 'o';
puts(otherstring);
return 0;
}
编译器是MS VC ++。
无论是否使用优化构建此程序,我都可以使用十六进制编辑器在可执行文件中找到字符串“ABCDEFGHIJKLMNO”。
但是,我找不到字符串“abcdefghijklmno”
编译器执行的操作对于其他字符串有什么不同?
我使用的十六进制编辑器是Hexedit - 但尝试了其他人但仍然找不到其他字符串。任何想法为什么没有或如何找到?
顺便说一句,我不是出于黑客的原因这样做的。
答案 0 :(得分:5)
这是我的gcc使用此代码所做的事情。我假设您的编译器做了类似的事情。字符串常量存储在只读部分,mystring用它的地址初始化 各个字符直接放在堆栈中的数组位置。另请注意,当您使用它调用puts时,otherstring不会以NULL结尾。
.file "test.c"
.section .rodata
.LC0:
.string "ABCDEFGHIJKLMNO"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $48, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
/* here is where mystring is loaded with the address of "ABCDEFGHIJKLMNO" */
movq $.LC0, -40(%rbp)
/* this is the call to puts */
movq -40(%rbp), %rax
movq %rax, %rdi
call puts
/* here is where the bytes are loaded into otherstring on the stack */
movb $97, -32(%rbp) //'a'
movb $98, -31(%rbp) //'b'
movb $99, -30(%rbp) //'c'
movb $100, -29(%rbp) //'d'
movb $101, -28(%rbp) //'e'
movb $102, -27(%rbp) //'f'
movb $103, -26(%rbp) //'g'
movb $104, -25(%rbp) //'h'
movb $105, -24(%rbp) //'i'
movb $106, -23(%rbp) //'j'
movb $107, -22(%rbp) //'k'
movb $108, -21(%rbp) //'l'
movb $109, -20(%rbp) //'m'
movb $110, -19(%rbp) //'n'
movb $111, -18(%rbp) //'o'
答案 1 :(得分:1)
编译器可能会将每个字符的编号放入每个数组位置,就像您编写它一样,而不会在读取代码时找到任何优化。请记住,单个字符与c中的数字没有区别,因此您甚至可以使用ascii代码而不是“a”。从一个hexeditor我希望你会看到那些转换回字母,只是间隔一点。
答案 2 :(得分:1)
在第一种情况下,编译器使用完全字符串“ABC ...”初始化数据。
在第二种情况下,每个赋值都是按顺序完成的,因此编译器会生成代码以执行此赋值。在可执行文件中,您应该看到15个重复的字节序列,其中只有初始化程序('a','b','c'...)发生变化。