Tag: 程序集

c库x86 / x64汇编程序

是否有用于将x86 / x64汇编字符串组装到操作码的C库? 示例代码: /* size_t assemble(char *string, int asm_flavor, char *out, size_t max_size); */ unsigned char bytes[32]; size_t size = assemble(“xor eax, eax\n” “inc eax\n” “ret”, asm_x64, &bytes, 32); for(int i = 0; i < size; i++) { printf("%02x ", bytes[i]); } /* Output: 31 C0 40 C3 */ 我看过asmpure ,但它需要修改才能在非Windows机器上运行。 我实际上都需要一个汇编器和一个反汇编器,是否有一个提供两者的库?

如何使用GCC将源代码行与汇编输出内联?

我想让C源代码行与汇编输出内联,以查看正在生成的代码。 我尝试过像-S -Wa,-ahlms这样的GCC选项(甚至-Wa,–gstabs因为我在某处读过它)。 哦! 顺便说一句,我在Mac上,所以我没有objdump 。 (对不起,这很简短,我必须下车!) 输出gcc pc-clisp.c -S -g -fverbose-asm -fnested-functions .globl _getBool _getBool: LFB32: LM21: pushl %ebp # LCFI30: movl %esp, %ebp #, LCFI31: subl $8, %esp #, LCFI32: LM22: movzbl 8(%ebp), %eax # atom.pred, D.4112 movzbl %al, %eax # D.4112, D.4113 andl $-16, %eax #, D.4114 sarl $4, %eax #, D.4115 […]

无法使用ld链接目标文件 – Mac OS X.

/********* exit.asm */ [SECTION .text] global _start _start: xor eax, eax xor ebx, ebx mov al, 1 int 0x80 //**************************** 首先,我使用nasm -f elf exit.asm生成目标文件。 然后我在我的Mac OS X 10.7上运行了以下“ld”命令,它有这些输出和警告,我试图在我的32位linux机器上运行它,一切都很顺利,请你解释为什么不会链接器在我的Mac上运行? 谢谢! Alfred says: ld -o exiter exit.o ld: warning: -arch not specified ld: warning: -macosx_version_min not specified, assuming 10.7 ld: warning: ignoring file exit.o, file was built […]

编写一个简单的Bootloader HelloWorld – 错误函数打印字符串

我尝试创建一个打印“hello world”的简单引导程序。 当我调用一个只打印“hello world”的函数时,我可以这样做,但是当我调用一个函数来打印一个特定的字符串时,什么也没发生。 为此,我使用两个文件。 第一个是boot.ld,第二个是boot.cpp(它也可以在C中使用boot.c)。 首先,我从终端创建软盘: dd if = / dev / zero of = floppy.img bs = 512 count = 2880 其次,我编译代码(boot.cpp和boot.ld): gcc -c -g -Os -m64 -ffreestanding -Wall -Werror boot.cpp -o boot.o ld -static -Tboot.ld -nostdlib –nmagic -o boot.elf boot.o objcopy -O binary boot.elf boot.bin 最后,我将boot.bin添加到floppy.img中: dd if = boot.bin of = […]

如何在GCC x86内联汇编中使用地址常量

GCC工具链默认使用AT&T汇编语法,但可通过.intel_syntax指令获得对Intel语法的支持。 此外,AT&T和Intel语法都有prefix和noprefix版本,不同之处在于它们是否需要使用% sigil为寄存器名称添加前缀。 根据存在的指令,地址常量的格式会发生变化。 我们考虑以下C代码 *(int *)0xdeadbeef = 0x1234; 使用objdump -d ,我们发现它被编译为以下汇编程序指令 movl $0x1234,0xdeadbeef 由于没有涉及寄存器,这是.att_syntax prefix和.att_syntax noprefix的正确语法,即。 嵌入在C代码中,它们看起来像这样 __asm__(“.att_syntax prefix”); __asm__(“movl $0x1234,0xdeadbeef”); __asm__(“.att_syntax noprefix”); __asm__(“movl $0x1234,0xdeadbeef”); 您可以选择用括号括起地址常量,即。 __asm__(“movl $0x1234,(0xdeadbeef)”); 也会奏效。 将sigil添加到普通地址常量时,代码将无法复制 __asm__(“movl $0x1234,$0xdeadbeef”); // won’t compile 当用paranthesis围绕这个表达式时,编译器会在没有警告的情况下发出错误的代码,即 __asm__(“movl $0x1234,($0xdeadbeef)”); // doesn’t warn, but doesn’t work! 这将错误地发出指令 movl $0x1234,0x0 在Intel模式下,如果可能存在歧义,则地址常量必须以段寄存器为前缀,并且必须以操作数大小和PTR标志为前缀。 在我的机器上(采用Windows XP和当前MinGW和Cygwin GCC版本的英特尔双核笔记本电脑),默认情况下使用寄存器ds 。 常量周围的方括号是可选的。 如果省略段寄存器但是括号存在,则也可以正确识别地址常量。 […]

如何使用内核创建可启动CD映像?

我有一个内核,要启动我正在使用命令qemu-system-i386 -kernel kernel.bin 。 有没有办法用qemu-system-i386 -cdrom CD.iso创建可引导的磁盘映像? 我在linux中用这些命令编译的代码: nasm -f elf32 kernel.asm -o kernelasm.o gcc -m32 -c kernel.c -o kernelc.o ld -m elf_i386 -T link.ld -o kernel.bin kernelasm.o kernelc.o 然后使用qemu-system-i386 -kernel kernel.bin 代码:kernel.asm: [BITS 32] SECTION .text align 4 dd 0x1BADB002 dd 0x00 dd – (0x1BADB002 + 0x00) global start global keyboard_handler global read_port global […]

跟踪/分析说明

我想在指令级别对我的C代码进行统计分析。 我需要知道我正在执行多少次加法,乘法,除法等。 这不是您通常的磨码分析要求。 我是算法开发人员,我想估算将代码转换为硬件实现的成本。 为此,我在运行时被问到指令调用故障(解析编译的程序集是不够的,因为它不考虑代码中的循环)。 环顾四周后,似乎VMware可能提供了一个可能的解决方案,但我仍然找不到能够跟踪我的进程的指令调用流的特定function。 你知道任何能够实现这一目标的分析工具吗?

今天和20年前的记忆对齐

在着名的论文“Smashing the Stack for Fun and Profit”中,它的作者采用了C函数 void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } 并生成相应的汇编代码输出 pushl %ebp movl %esp,%ebp subl $20,%esp 作者解释说,由于计算机以字大小的倍数寻址存储器,编译器在堆栈上保留20个字节(缓冲区1为8个字节,缓冲区2为12个字节)。 我试图重新创建这个例子并获得以下内容 pushl %ebp movl %esp, %ebp subl $16, %esp 不同的结果! 我尝试了缓冲区1和缓冲区2的各种大小组合,似乎现代的gcc不再将缓冲区大小填充到字大小的倍数。 相反,它遵循-mpreferred-stack-boundary选项。 作为一个例子 – 使用纸张的算术规则,对于buffer1 [5]和buffer2 [13],我会在堆栈上保留8 + 16 = 24个字节。 但实际上我有32个字节。 这篇论文很古老,自那以后发生了很多事情。 我想知道,究竟是什么推动了这种行为的改变? 这是向64位机器的转变吗? 或者是其他东西? 编辑 […]

检查Visual Studio C ++编译器生成的代码,第1部分

可能重复: 为什么发出这样复杂的代码来将有符号整数除以2的幂? 背景 我只是通过检查编译器生成的二进制代码来学习x86 asm。 在Visual Studio 2010 beta 2中使用C ++编译器编译的代码。 Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.21003.01 for 80×86 C代码(sandbox.c) int mainCRTStartup() { int x=5;int y=1024; while(x) { x–; y/=2; } return x+y; } 使用Visual Studio命令提示符编译它 cl /c /O2 /Oy- /MD sandbox.c link /NODEFAULTLIB /MANIFEST:NO /SUBSYSTEM:CONSOLE sandbox.obj 在OllyDgb中解雇sandbox.exe 以下从入口点开始。 00401000 >/$ B9 05000000 […]

GDB:尝试取消引用通用指针

如何使GDB在x/s等打印function中进行额外的解引用? 当我在x/ I中尝试显式解引用时,会出现错误“尝试取消引用通用指针”。 使用x/多次工作,因为每次使用都包含隐式解引用,但这很烦人,因为我必须复制并粘贴每个中间结果。 例 考虑非常有用的C程序, example.c : #include int main(int argc, char **argv) { printf(“argv[0] = %s\n”, argv[0]); } 如果我构建它并将其加载到GDB中,我看到argv存储在0xc(%ebp) ,因为它的双重因素作为第二个参数传递给第24行的printf (即0x4(%esp) ): $ gcc -o example example.c $ gdb example (gdb) disass main Dump of assembler code for function main: 0x080483e4 : push %ebp 0x080483e5 : mov %esp,%ebp 0x080483e7 : and $0xfffffff0,%esp 0x080483ea […]