相关疑难解决方法(0)

为什么GCC在实现整数除法时使用乘以奇数的乘法?

我一直在阅读divmul组装操作,我决定通过在C中编写一个简单的程序来实现它们:

文件分割

#include <stdlib.h>
#include <stdio.h>

int main()
{
    size_t i = 9;
    size_t j = i / 5;
    printf("%zu\n",j);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后生成汇编语言代码:

gcc -S division.c -O0 -masm=intel
Run Code Online (Sandbox Code Playgroud)

但是看生成的division.s文件,它不包含任何div操作!相反,它通过位移和魔术数字来做某种黑魔法.这是一个计算代码片段i/5:

mov     rax, QWORD PTR [rbp-16]   ; Move i (=9) to RAX
movabs  rdx, -3689348814741910323 ; Move some magic number to RDX (?)
mul     rdx                       ; Multiply 9 by magic number
mov     rax, rdx                  ; Take only the upper 64 bits of the …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 integer-division

206
推荐指数
4
解决办法
1万
查看次数

如何从GCC /铿锵声组件输出中消除"噪音"?

我想检查boost::variant在我的代码中应用的程序集输出,以便查看哪些中间调用被优化掉了.

当我编译以下示例(使用GCC 5.3 g++ -O3 -std=c++14 -S)时,似乎编译器优化了所有内容并直接返回100:

(...)
main:
.LFB9320:
    .cfi_startproc
    movl    $100, %eax
    ret
    .cfi_endproc
(...)
Run Code Online (Sandbox Code Playgroud)
#include <boost/variant.hpp>

struct Foo
{
    int get() { return 100; }
};

struct Bar
{
    int get() { return 999; }
};

using Variant = boost::variant<Foo, Bar>;


int run(Variant v)
{
    return boost::apply_visitor([](auto& x){return x.get();}, v);
}
int main()
{
    Foo f;
    return run(f);
}
Run Code Online (Sandbox Code Playgroud)

但是,完整的程序集输出包含的内容远远超过上面的摘录,对我而言,它看起来永远不会被调用.有没有办法告诉GCC/clang删除所有"噪音"并输出程序运行时实际调用的内容?


完整装配输出:

    .file   "main1.cpp"
    .section    .rodata.str1.8,"aMS",@progbits,1
    .align 8
.LC0:
    .string "/opt/boost/include/boost/variant/detail/forced_return.hpp"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC1: …
Run Code Online (Sandbox Code Playgroud)

c++ assembly gcc clang

56
推荐指数
3
解决办法
1万
查看次数

为什么 GCC 分配的堆栈内存比需要的多?

我正在阅读“计算机系统:程序员的视角,3/E”(CS:APP3e),以下代码是书中的示例:

long call_proc() {
    long  x1 = 1;
    int   x2 = 2;
    short x3 = 3;
    char  x4 = 4;
    proc(x1, &x1, x2, &x2, x3, &x3, x4, &x4);
    return (x1+x2)*(x3-x4);
}
Run Code Online (Sandbox Code Playgroud)

书中给出了GCC生成的汇编代码:

long call_proc()
call_proc:
    ; Set up arguments to proc
    subq    $32, %rsp           ; Allocate 32-byte stack frame
    movq    $1, 24(%rsp)        ; Store 1 in &x1
    movl    $2, 20(%rsp)        ; Store 2 in &x2
    movw    $3, 18(%rsp)        ; Store 3 in &x3
    movb    $4, 17(%rsp)        ; Store 4 in …
Run Code Online (Sandbox Code Playgroud)

c gcc x86-64 compiler-optimization stack-memory

8
推荐指数
1
解决办法
678
查看次数

这个128位整数乘法如何在汇编(x86-64)中工作?

我正在阅读计算机系统:程序员的观点,家庭作业是描述这种算法是如何工作的.

C功能:

void store_prod(__int128 *dest, int64_t x, int64_t y) {
    *dest = x * (__int128)y;
}
Run Code Online (Sandbox Code Playgroud)

部件:

movq %rdx, %rax
cqto
movq  %rsi, %rcx
sarq  $63,  %rcx
imulq %rax, %rcx
imulq %rsi, %rdx
addq  %rdx, %rcx
mulq  %rsi
addq  %rcx, %rdx
movq  %rax, (%rdi)
movq  %rdx, 8(%rdi)
ret
Run Code Online (Sandbox Code Playgroud)

我不知道它为什么表现: xh * yl + yh * xl = value which we add after unsigned multiplication

c assembly x86-64 128-bit

7
推荐指数
2
解决办法
2007
查看次数

何时以及为什么我们签署扩展并使用cdq与mul/div?

我今天进行了测试,我唯一不理解的问题是将双字转换为四字.

这让我思考,为什么/我们什么时候签署扩展乘法或除法?另外,我们何时使用像cdq这样的指令?

x86 assembly sign-extension

5
推荐指数
1
解决办法
6671
查看次数

这个只有一个操作数的 x86-64 addq 指令是什么意思?(摘自CSAPP书籍第三版)

在下面的说明中,addq 是如何工作的?它只有一个操作数,书上声称它递增 %rdx,但 %rdx 不在这条指令中。我感到很困惑...

这是来自《计算机系统程序员视角》一书,第三版。

在此输入图像描述

在此输入图像描述

在此输入图像描述

x86 assembly computer-science x86-64

5
推荐指数
1
解决办法
3571
查看次数

x86 汇编器中的除法

我的大学给了我一个练习:

1.在Jasmin中创建一个新文档

2. 使用 AL 寄存器将 9 加到 8。

3. 减去 2。

4. 除以 7。

我的解决方案是:

mov al,9
add al,8
sub al,2
Run Code Online (Sandbox Code Playgroud)

但如何除以 7 呢?我尝试过类似的方法,div al,7但这不起作用。

x86 assembly

2
推荐指数
1
解决办法
4万
查看次数

为什么使用xor而不是mov需要更少的字节?

当将x设置为零(x = 0)时,我的csapp书指出了两种方法。

第一:

xorq %rcx, %rcx
Run Code Online (Sandbox Code Playgroud)

第二:

movq $0, %rcx
Run Code Online (Sandbox Code Playgroud)

它还表明第一个仅占用3个字节,而第二个仅占用7个字节。

两种方式如何运作?为什么第一个字节比第二个字节少?

assembly x86-64 machine-code code-size

1
推荐指数
1
解决办法
96
查看次数

在使用DIV指令之前,为什么EDX应为0?

我注意到EDX包含一些随机默认值,如00401000,然后我使用这样的DIV指令:

mov eax,10
mov ebx,5
div ebx
Run Code Online (Sandbox Code Playgroud)

它会导致INTEGER OVERFLOW ERROR.但是,如果我设置edx为0并执行相同的操作.我相信使用div会导致商重写eax和其余覆盖edx.

获得此INTEGER OVERFLOW ERROR确实让我感到困惑.

x86 assembly integer-division

0
推荐指数
1
解决办法
5017
查看次数

如何从 switch 语句获取跳转表的案例编号

我正在阅读这本教科书,Randal E. Bryant、David R. O\xe2\x80\x99Hallaron - 计算机系统。A Programmer\xe2\x80\x99s Perspective [3rd ed.] (2016, Pearson)
\n我一直在弄清楚作者如何计算出开关表的案例编号,如下所示~

\n

我不确定的是他们如何获得案例编号,例如Case Ais Case 5: 以及如何Case 2/7isCase CCase D,对于本示例中的其余案例,依此类推

\n

任何帮助表示感谢,谢谢!!

\n

开关指令

\n

汇编代码

\n

给出答案

\n

c x86 assembly switch-statement jump-table

0
推荐指数
1
解决办法
1170
查看次数