Questions tagged «assembly»

汇编语言(asm)编程问题。确保还标记您正在使用的处理器和/或指令集以及汇编器。警告:对于.NET程序集,请使用标签[.net-assembly]。对于Java ASM,请改用标记[java-bytecode-asm]。

2
x86_64汇编器中RBP寄存器的用途是什么?
所以我尝试学习一些汇编,因为计算机架构课程需要它。我写了一些程序,例如打印斐波那契数列。 我认识到,每当我编写一个函数时,我都会使用这三行代码(正如我从将生成的汇编代码gcc与其C等效代码进行比较中学到的那样): pushq %rbp movq %rsp, %rbp subq $16, %rsp 我对此有2个问题: 首先,为什么我需要使用%rbp?%rsp它的内容移至%rbp第二行,使用起来更简单吗? 为什么我必须从中减去任何东西%rsp?我的意思是,并非总是如此16,当我要printf输入7或8个变量时,我会减去24或28。 我在虚拟机(4 GB RAM)和Intel 64位处理器上使用Manjaro 64位

9
为什么“不归还”功能归还?
我读 这个问题关于noreturn属性,它被用于那些不返回到调用函数。 然后我用C编写了一个程序。 #include <stdio.h> #include <stdnoreturn.h> noreturn void func() { printf("noreturn func\n"); } int main() { func(); } 并使用此生成的代码汇编: .LC0: .string "func" func: pushq %rbp movq %rsp, %rbp movl $.LC0, %edi call puts nop popq %rbp ret // ==> Here function return value. main: pushq %rbp movq %rsp, %rbp …

2
在x86汇编中使用哪个可变大小(db,dw,dd)?
我是汇编的初学者,我不知道所有db,dw,dd的含义是什么。我试图编写一个执行1 + 1的小脚本,将其存储在变量中,然后显示结果。到目前为止,这是我的代码: .386 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\masm32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\masm32.lib .data num db ? ; set variable . Here is where I don't know what data type to use. .code start: mov eax, 1 ; add 1 to eax register …

2
为什么使用三元运算符返回字符串与返回等效的if / else块会产生截然不同的代码?
我在使用Compiler Explorer时,偶然发现使用三元运算符时会发生以下有趣的行为: std::string get_string(bool b) { return b ? "Hello" : "Stack-overflow"; } 编译器为此生成的代码(带有-O3的Clang干线)是这样的: get_string[abi:cxx11](bool): # @get_string[abi:cxx11](bool) push r15 push r14 push rbx mov rbx, rdi mov ecx, offset .L.str mov eax, offset .L.str.1 test esi, esi cmovne rax, rcx add rdi, 16 #< Why is the compiler storing the …

6
用于memcpy的增强型REP MOVSB
我想使用增强的REP MOVSB(ERMSB)为自定义获取高带宽memcpy。 ERMSB是与Ivy Bridge微体系结构一起引入的。如果您不知道什么是ERMSB,请参阅英特尔优化手册中的“增强型REP MOVSB和STOSB操作(ERMSB)”部分。 我知道直接执行此操作的唯一方法是内联汇编。我从https://groups.google.com/forum/#!topic/gnu.gcc.help/-Bmlm_EG_fE获得了以下功能 static inline void *__movsb(void *d, const void *s, size_t n) { asm volatile ("rep movsb" : "=D" (d), "=S" (s), "=c" (n) : "0" (d), "1" (s), "2" (n) : "memory"); return d; } 但是,当我使用它时,带宽远小于memcpy。 我的i7-6700HQ(Skylake)系统,Ubuntu 16.10,DDR4 @ 2400 MHz双通道32 GB,GCC 6.2可达到__movsb15 GB / …
71 c  gcc  assembly  x86  memcpy 

3
C ++:将一个操作数保留在寄存器中的速度大大提高
我一直在尝试通过定时使用以下代码对数组元素进行缩放和求和的例程来了解在L1缓存中存储数组对内存的影响(我知道我应该将结果按'最后是a';关键是要在循环内进行乘法和加法-到目前为止,编译器尚未弄清楚要分解出'a'): double sum(double a,double* X,int size) { double total = 0.0; for(int i = 0; i < size; ++i) { total += a*X[i]; } return total; } #define KB 1024 int main() { //Approximately half the L1 cache size of my machine int operand_size = (32*KB)/(sizeof(double)*2); printf("Operand size: %d\n", operand_size); …

4
为什么构造std :: optional <int>比std :: pair <int,bool>昂贵?
考虑以下两种可以表示“可选int”的方法: using std_optional_int = std::optional&lt;int&gt;; using my_optional_int = std::pair&lt;int, bool&gt;; 鉴于这两个功能... auto get_std_optional_int() -&gt; std_optional_int { return {42}; } auto get_my_optional() -&gt; my_optional_int { return {42, true}; } ... g ++干线和clang ++干线 (带有-std=c++17 -Ofast -fno-exceptions -fno-rtti)都会产生以下汇编: get_std_optional_int(): mov rax, rdi mov DWORD PTR [rdi], 42 mov BYTE PTR [rdi+4], 1 …

4
x86汇编中的“锁定”指令是什么意思?
我在Qt的源代码中看到了一些x86程序集: q_atomic_increment: movl 4(%esp), %ecx lock incl (%ecx) mov $0,%eax setne %al ret .align 4,0x90 .type q_atomic_increment,@function .size q_atomic_increment,.-q_atomic_increment 从谷歌搜索,我知道lock指令将导致CPU锁定总线,但是我不知道CPU何时释放总线? 关于上面的整个代码,我不明白该代码如何实现Add?
69 c++  qt  assembly  x86 

3
这是“不应发生”崩溃的AMD Fusion CPU错误吗?
由于我们的程序由于系统上的访问冲突而崩溃,因此我的公司已经开始吸引许多客户。 崩溃发生在SQLite 3.6.23.1中,我们将其作为应用程序的一部分提供。(为了提供与应用程序其余部分相同的VC ++库,我们提供了一个自定义版本,但这是库存的SQLite代码。) 当pcache1Fetch执行时发生崩溃call 00000000,如WinDbg调用栈所示: 0b50e5c4 719f9fad 06fe35f0 00000000 000079ad 0x0 0b50e5d8 719f9216 058d1628 000079ad 00000001 SQLite_Interop!pcache1Fetch+0x2d [sqlite3.c @ 31530] 0b50e5f4 719fd581 000079ad 00000001 0b50e63c SQLite_Interop!sqlite3PcacheFetch+0x76 [sqlite3.c @ 30651] 0b50e61c 719fff0c 000079ad 0b50e63c 00000000 SQLite_Interop!sqlite3PagerAcquire+0x51 [sqlite3.c @ 36026] 0b50e644 71a029ba 0b50e65c 00000001 00000e00 SQLite_Interop!getAndInitPage+0x1c [sqlite3.c @ 40158] 0b50e65c 71a030f8 …

1
x86指令是否需要自己的编码以及所有参数同时出现在内存中?
我试图弄清楚是否有可能运行仅由单个物理页面支持其RAM的Linux VM。 为了模拟这一点,我修改了KVM中的嵌套页面错误处理程序,以从所有嵌套页面表(NPT)条目中删除当前位,但与当前正在处理的页面错误相对应的位除外。 在尝试启动Linux guest虚拟机时,我观察到使用内存操作数的汇编指令,例如 add [rbp+0x820DDA], ebp 导致页面错误循环,直到我恢复包含指令的页面以及操作数中引用的页面的当前位(在本示例中[rbp+0x820DDA])。 我想知道为什么会这样。CPU是否不应该按顺序访问内存页面,即先读取指令然后访问内存操作数?还是x86要求同时访问指令页面以及所有操作数页面? 我正在AMD Zen 1上进行测试。

1
为什么GCC聚合数组的初始化会首先用零填充整个东西,包括非零元素?
为什么gcc用零而不是仅剩余的96个整数填充整个数组?非零初始值设定项都在数组的开头。 void *sink; void bar() { int a[100]{1,2,3,4}; sink = a; // a escapes the function asm("":::"memory"); // and compiler memory barrier // forces the compiler to materialize a[] in memory instead of optimizing away } MinGW8.1和gcc9.2都使asm像这样(Godbolt编译器资源管理器)。 # gcc9.2 -O3 -m32 -mno-sse bar(): push edi # save call-preserved EDI which …

1
为什么GCC不能假设std :: vector :: size在此循环中不会改变?
我要求一个if (i &lt; input.size() - 1) print(0);在此循环中得到优化的同事,这样input.size()就不会在每次迭代中都读取它,但事实证明并非如此! void print(int x) { std::cout &lt;&lt; x &lt;&lt; std::endl; } void print_list(const std::vector&lt;int&gt;&amp; input) { int i = 0; for (size_t i = 0; i &lt; input.size(); i++) { print(input[i]); if (i &lt; input.size() - 1) print(0); } } 根据带有gcc选项的Compiler Explorer,-O3 -fno-exceptions我们实际上是在读取input.size()每个迭代并lea用于执行减法运算! movq …
14 c++  gcc  assembly 

1
精确的机器代码副本运行速度比原始功能慢50%
我一直在尝试从嵌入式系统上的RAM和闪存执行性能。为了快速进行原型制作和测试,我目前使用的是Arduino Due(SAM3X8E ARM Cortex-M3)。据我所知,Arduino运行时和引导程序在这里应该没有任何区别。 这是问题所在:我有一个用ARM Thumb Assembly编写的函数(calc)。calc计算一个数字并将其返回。(对于给定的输入,&gt; 1s运行时)现在,我手动提取了该函数的汇编机器代码,并将其作为原始字节放入另一个函数中。确认这两个功能都驻留在闪存中(地址0x80149和0x8017D紧挨着)。通过反汇编和运行时检查已确认了这一点。 void setup() { Serial.begin(115200); timeFnc(calc); timeFnc(calc2); } void timeFnc(int (*functionPtr)(void)) { unsigned long time1 = micros(); int res = (*functionPtr)(); unsigned long time2 = micros(); Serial.print("Address: "); Serial.print((unsigned int)functionPtr); Serial.print(" Res: "); Serial.print(res); Serial.print(": "); Serial.print(time2-time1); Serial.println("us"); } int calc() { asm …

1
为何编译器坚持在此处使用被调用者保存的寄存器?
考虑下面的C代码: void foo(void); long bar(long x) { foo(); return x; } 当我在GCC 9.3上使用-O3或编译它时-Os,得到以下信息: bar: push r12 mov r12, rdi call foo mov rax, r12 pop r12 ret clang的输出是相同的,除了选择rbx而不是r12作为被调用者保存的寄存器。 但是,我希望/希望看到看起来像这样的程序集: bar: push rdi call foo pop rax ret 用英语,这就是我所看到的: 将已保存被调用者的寄存器的旧值推入堆栈 移动x到该被调用方保存寄存器 呼叫 foo 移动x从被调用者被保存的寄存器到返回值寄存器 弹出堆栈以恢复被调用方保存的寄存器的旧值 为什么要弄乱所有保存在被调用方中的寄存器?为什么不这样做呢?它看起来更短,更简单,并且可能更快: 推x入栈 呼叫 foo x从堆栈弹出到返回值寄存器 我的大会错了吗?它比以多余的寄存器搞乱效率低吗?如果对这两个问题的回答都是“否”,那么为什么GCC或clang都不这样做呢? …
10 c  gcc  assembly  clang  x86-64 

1
为什么在加载.COM文件后DOS将SP寄存器设置为0xFFFE?
在有关.COM文件https://en.wikipedia.org/wiki/COM_file的wikpedia页面上,其内容为: DOS中的.COM文件将所有x86段寄存器设置为相同的值,而SP(堆栈指针)寄存器设置为0xFFFE,因此,堆栈从内存段的最顶部开始,并从那里开始向下工作。 但这实际上将堆栈设置为在该段的顶部下方开始一个单词。当将值压入堆栈时,CPU会将SP递减至0xFFFC并将其存储在该值中,从而浪费了该段的最高字。DOS不将SP设置为0的原因是什么?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.