Tag: 汇编

如何防止strcpy()被优化

我在“黑客:剥削的艺术”一书中有一个例子,我对这本书的结果有所不同。 似乎示例中的strcpy()函数编译为如下指令: 0x802384c5 : call 0x80482C4 而当我编译相同的程序时,它会删除对库的调用,并用一系列mov指令替换它: 0x8048475 : mov DWORD PTR [eax],0x6c6c6548 0x804847b : mov DWORD PTR [eax+0x4],0x6f57206f 0x8048482 : mov DWORD PTR [eax+0x8],0x21646c72 0x8048489 : mov WORD PTR [eax+0xc],0xa 我知道编译器可以进行各种优化,但即使它是默认值,我甚至尝试用-O0编译它,这应该是为了防止优化。 如何编译代码以便引用外部库? 自从大学以来,我没有做任何C或组装,所以请对我温柔:)

Clang使用-nostdlib生成崩溃代码

我正在为可执行文件设置我自己的运行时环境,我不能得到clang(v3.4-1ubuntu1,target:x86_64-pc-linux-gnu)来生成一个不会发生段错误的可执行文件。 我已将问题减少到以下几点: 如果我有一个文件crt1.c除了满足_start符号的链接器要求之外什么都不做: void _start(char *arguments, …) { } 然后我用clang -nostdlib crt1.c编译它,它产生以下可执行文件(来自objdump -d a.out ): a.out: file format elf64-x86-64 Disassembly of section .text: 0000000000400150 : 400150: 55 push %rbp 400151: 48 89 e5 mov %rsp,%rbp 400154: 48 81 ec f0 00 00 00 sub $0xf0,%rsp 40015b: 84 c0 test %al,%al 40015d: 0f 29 bd 30 […]

内存间接寻址movl – assembly

我试图通过AT&T语法了解内存间接寻址在汇编语言中是如何工作的。 movl (%eax), %ebx movl %eax, (%ebx) 这是一个类似的问题,解释了内存间接寻址 这就是我所理解的: 在第一种情况下,您load寄存器%eax指向的数据并将其存储在%ebx 。 在第二种情况下,将寄存器%eax的数据store到寄存器%ebx指向的地址空间。 我对么?

Not Null Terminated字符数组

#include char s[3] = “Robert”; int main() { printf(“%s”,s); } Output: Rob 如何正确打印? 该字符串不是以null结尾。 我看到了集会。 它使用.ascii存储“Rob”,它不是空终止的。 我期待一些垃圾和Rob一起打印。 有人可以解释我这种行为吗?

为什么这个IA32汇编代码有三个leal指令?

我编译了这个C函数: int calc(int x, int y, int z) { return x + 3*y + 19*z; } 我在calc.s中得到了这个,我正在注释正在发生的事情: .file “calc.c” .text .globl calc .type calc, @function calc: pushl %ebp //Save paramaters movl %esp, %ebp //Move stack pointer into %ebp movl 12(%ebp), %eax //Move y into %eax movl 16(%ebp), %ecx //Move z into %ecx leal (%eax,%eax,2), %eax […]

有和没有辅助变量的可变交换 – 哪个更快?

我想你们都听说过“交换问题”; SO充满了关于它的问题。 不使用第三个变量的交换版本通常被认为更快,因为你有一个变量更少。 我想知道窗帘后面发生了什么,并编写了以下两个程序: int main () { int a = 9; int b = 5; int swap; swap = a; a = b; b = swap; return 0; } 和没有第三个变量的版本: int main () { int a = 9; int b = 5; a ^= b; b ^= a; a ^= b; return 0; } […]

循环通过arraysMIPS汇编

我正在研究一个循环通过10个数字的数组的程序。 前9个元素的值大于0,第10个元素的值为0.当遇到0时,循环应该中断。 i=0; while(A[i]!=0) { A[i]=A[i]+1; i++; } 我知道如果寄存器的值等于0,我可以使用’beq’来打破循环。但是我不太了解操作内存中的值。 这是我第一次使用MIPS,你会发现它很乱。 如果你不能帮我解决,你能给我一些指示吗? .data #by default, the “data segment” starts at address 0x10010000 .word 1 .word 2 .word 3 .word 4 .word 5 .word 6 .word 7 .word 8 .word 9 .word 0 .text #instructions start below # MIPS assembly code lui $a0, 0x1001 # $a0 = […]

分配新的调用堆栈

(我认为这个问题很可能已经重复或者已经在这里回答了,但是由于“堆栈分配”和相关术语的干扰,寻找答案很难。) 我有一个玩具编译器,我一直在研究脚本语言。 为了能够在脚本正在进行时暂停执行并返回到主机程序,它有自己的堆栈:带有“堆栈指针”变量的简单内存块,使用正常的C代码操作递增对于那种事情等等。 到目前为止没有意思。 目前我编译为C.但我也有兴趣调查编译机器代码 – 同时保持二级堆栈和在预定义控制点返回主机程序的能力。 所以…我认为在我自己的代码中使用传统的堆栈寄存器不太可能是一个问题,我假设寄存器会发生什么,只要一切都在我完成时就恢复了(如果我做的话,请纠正我)在这一点上我错了。 但是 ……如果我希望脚本代码调用其他库代码,使用这个“虚拟堆栈”离开程序是否安全,或者是否必须为此目的返回原始堆栈? 像这一个和这一个的答案表明堆栈不是传统的内存块,但它依赖于特殊的,系统特定的行为来处理页面错误和诸如此类的东西。 所以: 将堆栈指针移动到其他内存区域是否安全? 堆栈内存不是“特殊”? 我认为线程库必须做这样的事情,因为它们会创建更多的堆栈…… 假设使用堆栈寄存器和指令操作任何内存区域都是安全的,我可以认为没有理由调用任何具有已知调用深度的函数(即没有递归,没有函数指针)是一个问题,只要这样做金额在虚拟堆栈上可用。 对? 无论如何,堆栈溢出在普通代码中显然是一个问题,但是对于这样的系统中的溢出会有任何额外的灾难性后果吗? 这显然不是必需的,因为简单地将指针返回到实际堆栈将是完全可用的,或者就此而言,首先不要滥用它们并且只是放置更少的寄存器,我可能不应该尝试这样做完全(尤其是因为显然不在我的深处)。 但无论如何我仍然很好奇。 想知道这些事情是如何运作的。 编辑:对不起,当然应该说。 我正在研究x86(我自己的机器为32位),Windows和Ubuntu。 没有异国情调。

高阶位 – 取出它们并将uint64_t转换为uint8_t

假设您有一个uint64_t,并且只关心uint64_t中每个字节的高位。 像这样: uint32_t:0000 … 1000 0000 1000 0000 1000 0000 1000 0000 —> 0000 1111 有没有比以下更快的方式: return ( ((x >> 56) & 128)+ ((x >> 49) & 64)+ ((x >> 42) & 32)+ ((x >> 35) & 16)+ ((x >> 28) & 8)+ ((x >> 21) & 4)+ ((x >> 14) & 2)+ ((x >> […]

与iPhone项目一起编译程序集(.S)文件

在我的iPhone项目中,我有一个名为arm_asm_stub.S的程序集文件,其中包含我需要从项目中名为main.c的另一个文件调用的方法。 当我没有#include我的main.c文件顶部的文件时,我没有得到构建错误,但我确实得到了链接器错误: Undefined symbols for architecture armv7: “_execute_arm_translate”, referenced from: _iphone_main in main.o 但是,当我尝试#include main.c顶部的文件时,Xcode使用Clang来编译arm_asm_stub.S所以我得到了一堆错误,当我不#include文件时出现错误如: unknown type name ‘ldr’ expected identifier or ‘(‘ use of undeclared identifier ‘sp’ Xcode如何分别编译这个文件而不是项目的其余部分?