我首先注意到2009年gcc(至less在我的项目和我的机器上)有倾向于生成明显更快的代码,如果我优化大小 ( -Os ),而不是速度( -O2或-O3 ),我一直想知道为什么。 我已经设法创build(相当愚蠢的)代码,显示这个令人惊讶的行为,并足够小,在这里张贴。 const int LOOP_BOUND = 200000000; __attribute__((noinline)) static int add(const int& x, const int& y) { return x + y; } __attribute__((noinline)) static int work(int xval, int yval) { int sum(0); for (int i=0; i<LOOP_BOUND; ++i) { int x(xval+sum); int y(yval+sum); int z = add(x, y); sum += z; […]
Dump of assembler code for function func4 <+0>: mov %rbx,-0x18(%rsp) <+5>: mov %rbp, -0x10(%rsp) <+10>: mov %r12,-0x8(%rsp) <+15>: sub $0x18,%rsp <+19>: mov %edi,%ebx <+21>: mov %esi,%ebp <+23>: test %edi, %edi <+25>: jg 0x400fb2<func4+34> <+27>: mov $0x0,%ebp <+32>: jmp 0x400fd2<func4+66> <+34> cmp $0x1, %edi <+37>: je 0x400fd2<func4+66> <+39>: lea -0x1(%rbx),%edi <+42>: callq 0x400f90 <func4> <+47>: mov […]
我有一段C代码调用在程序集中定义的函数。 举例来说,假设foo.c包含: int bar(int x); /* returns 2x */ int main(int argc, char *argv[]) { return bar(7); } 而bar.s包含x86汇编中bar()的实现: .global bar bar: movl 4(%esp), %eax addl %eax, %eax ret 在Linux上,我可以很容易地编译和链接这些来源与GCC如下: % gcc -o test foo.c bar.s % ./test; echo $? 14 在使用MinGW的Windows上,失败的错误是“未定义的引用”bar“”。 原因是这样的,在Windows上所有带有C调用约定的函数的标识符都以下划线作为前缀,但是由于在汇编中定义了“bar”,所以它不会得到这个前缀,并且链接失败。 (所以这个错误信息实际上是抱怨丢失了_bar符号,而不是吧。) 总结: % gcc -c foo.c bar.s % nm foo.o bar.o foo.o: […]
我已经开始在我的Z80内核上实现ADD A和R操作码。 对于我认为已经固定的携带和溢出标志,我有一些疑惑,但是我想把它放到社区来检查我是否正确。 基本上,从我所看到的,Z80中的ALU不关心有符号/无符号操作,它只是增加了一些位。 这意味着如果将两个8位值相加在一起,并且由于它们的相加而产生9位值,则进位标志将被设置。 这包括增加两个负数的二进制补码,例如-20(11101100)和-40(11011000),结果虽然是-60(11000100),结果实际上是一个9位值1 1100 0100.这肯定意味着如果加两个负二进制补码值,即使没有溢出条件,进位标志也会一直置位 – 对吗? 其次,我决定要检测这条指令中的溢出,我将异或操作数的第7位,如果结果是10000000,那么肯定没有溢出 – 如果结果是00000000,那么可能会有溢出这些符号是相同的,因此,我将异或操作数的第7位加上结果的第7位,如果结果是10000000,则发生溢出,并设置P / V溢出标志。 我也在这里吗? 对不起,这样一个复杂的问题,我很确定我是对的,但我需要知道之前,我继续无数更多的指令基于这个逻辑。 非常感谢。
gcc -S选项会在AT&T语法中生成汇编代码,有没有一种方法可以在英特尔语法中生成文件? 或者有没有办法在两者之间进行转换?
从我上次编码的arm汇编程序起,我已经有一段时间了,细节上我有点生疏。 如果我从arm调用C函数,我只需要担心保存r0-r3和lr,对吧? 如果C函数使用其他寄存器,是否负责将这些寄存器保存在堆栈中并恢复它们? 换句话说,编译器会为C函数生成代码。 例如,如果我在汇编函数中使用r10,我不必将其值推入堆栈或内存,并在C调用后popup/恢复它,是吗? 这是为arm-eabi-gcc 4.3.0。 我意识到我可以阅读整个EABI,但是那么缩写RTFM就是为了什么,对吧? 🙂
我正在写小操作系统 – 用于练习。 我开始使用bootloader。 我想创build一个运行在16位真实模式(现在)的小型命令系统。 我已经创build了bootloader来重置驱动器,然后在bootloader之后加载扇区。 问题是因为jmp函数没有实际发生。 我试图加载下一个扇区在0x7E00(我不完全确定如何使用es:bx指向地址,这可能是一个问题,我相信它的地址:偏移量),就在bootloader之后。 这是代码: ; ; SECTOR 0x0 ; ;dl is number of harddrive where is bootloader org 0x7C00 bits 16 ;reset hard drive xor ah,ah int 0x13 ;read sectors clc mov bx,0x7E00 mov es,bx xor bx,bx mov ah,0x02 ;function mov al,0x1 ;sectors to read mov ch,0x0 ;tracks mov cl,0x1 […]