我希望能够%rbp在内联asm中使用基指针寄存器().这样的玩具示例是这样的:
void Foo(int &x)
{
asm volatile ("pushq %%rbp;" // 'prologue'
"movq %%rsp, %%rbp;" // 'prologue'
"subq $12, %%rsp;" // make room
"movl $5, -12(%%rbp);" // some asm instruction
"movq %%rbp, %%rsp;" // 'epilogue'
"popq %%rbp;" // 'epilogue'
: : : );
x = 5;
}
int main()
{
int x;
Foo(x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望,因为我使用通常的序幕/结尾函数调用方法来推送和弹出旧的%rbp,这样就可以了.但是,当我尝试在内x联asm之后访问时,它会出现故障.
GCC生成的汇编代码(略微剥离)是:
_Foo:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
# INLINEASM
pushq %rbp; // prologue
movq %rsp, …Run Code Online (Sandbox Code Playgroud) 在汇编编程中,想要从寄存器的低位计算某些东西是相当普遍的,这些位不能保证将其他位置零.在像C这样的高级语言中,你只需将输入转换为小尺寸,让编译器决定是否需要分别将每个输入的高位归零,或者是否可以在输出之后切断结果的高位.事实.
这是为x86-64的(又名AMD64),出于各种原因尤其常见1,其中的一些是存在于其它的ISA.
我将使用64位x86作为示例,但目的是询问/讨论2的补码和无符号二进制算法,因为所有现代CPU都使用它.(注意,C和C++不保证两个补码4,并且有符号溢出是未定义的行为.)
作为示例,考虑一个可以编译为LEA指令2的简单函数.(在X86-64 SysV的(Linux)的ABI 3,前两个函数参数是rdi和rsi,与在返回rax. int是一个32位的类型.)
; int intfunc(int a, int b) { return a + b*4 + 3; }
intfunc:
lea eax, [edi + esi*4 + 3] ; the obvious choice, but gcc can do better
ret
Run Code Online (Sandbox Code Playgroud)
gcc知道即使是负有符号整数,加法也只是从右到左,所以输入的高位不会影响进入的内容eax.因此,它保存了一个指令字节并使用 lea eax, [rdi + rsi*4 + 3]
为什么它有效?
1为什么x86-64频繁出现这种情况:x86-64有可变长度指令,其中额外的前缀字节改变了操作数大小(从32到64或16),因此在指令中通常可以保存一个字节.以相同的速度执行.当写入低8b或16b的寄存器(或稍后读取完整寄存器(Intel pre-IvB)时的失速)时,它也具有错误依赖性(AMD/P4/Silvermont):由于历史原因, …
给定N元素,仅处理第一个(0)和最后一个(N-1)元素.
但是,如果N = 1只处理单个元素一次.
使用一个或两次运行的循环,可以避免重复循环体.如果有一种可读的方法,那么它对源代码大小有好处.如果循环体很大,它也可能对机器代码大小有好处,并且编译器最终不会复制它.
我试过递增N-1但是当N=1(永远循环)时它不起作用.有没有技巧(反向循环fi)来解决这个问题?
for (i = 0 ; i < N ; i += (N - 1))
Run Code Online (Sandbox Code Playgroud)
我原来的问题涉及x,y,z方向的三个嵌套循环,这就是为什么我不能只处理elem [0])和elem [N-1].现在我有以下内容
#define forEachLglBound(i_,j_,k_) \
for(Int i_ = 0;i_ < NPX;i_+=((NPX>1) ? (NPX-1) : 1)) \
for(Int j_ = 0;j_ < NPY;j_+=((NPY>1) ? (NPY-1) : 1)) \
for(Int k_ = 0;k_ < NPZ;k_+=((NPZ>1) ? (NPZ-1) : 1))
Run Code Online (Sandbox Code Playgroud)
我正在学习用DOS和内联汇编在DOS下做一些低级VGA编程.现在我正在尝试创建一个在屏幕上打印出一个角色的功能.
这是我的代码:
//This is the characters BITMAPS
uint8_t characters[464] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x50,
0x50,0x00,0x00,0x00,0x00,0x00,0x50,0xf8,0x50,0x50,0xf8,0x50,0x00,0x20,0xf8,0xa0,
0xf8,0x28,0xf8,0x00,0xc8,0xd0,0x20,0x20,0x58,0x98,0x00,0x40,0xa0,0x40,0xa8,0x90,
0x68,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x20,0x40,0x40,0x40,0x40,0x20,0x00,
0x20,0x10,0x10,0x10,0x10,0x20,0x00,0x50,0x20,0xf8,0x20,0x50,0x00,0x00,0x20,0x20,
0xf8,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x60,0x20,0x40,0x00,0x00,0x00,0xf8,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x08,0x10,0x20,0x40,0x80,
0x00,0x70,0x88,0x98,0xa8,0xc8,0x70,0x00,0x20,0x60,0x20,0x20,0x20,0x70,0x00,0x70,
0x88,0x08,0x70,0x80,0xf8,0x00,0xf8,0x10,0x30,0x08,0x88,0x70,0x00,0x20,0x40,0x90,
0x90,0xf8,0x10,0x00,0xf8,0x80,0xf0,0x08,0x88,0x70,0x00,0x70,0x80,0xf0,0x88,0x88,
0x70,0x00,0xf8,0x08,0x10,0x20,0x20,0x20,0x00,0x70,0x88,0x70,0x88,0x88,0x70,0x00,
0x70,0x88,0x88,0x78,0x08,0x70,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x30,0x30,
0x00,0x30,0x10,0x20,0x00,0x00,0x10,0x20,0x40,0x20,0x10,0x00,0x00,0xf8,0x00,0xf8,
0x00,0x00,0x00,0x00,0x20,0x10,0x08,0x10,0x20,0x00,0x70,0x88,0x10,0x20,0x00,0x20,
0x00,0x70,0x90,0xa8,0xb8,0x80,0x70,0x00,0x70,0x88,0x88,0xf8,0x88,0x88,0x00,0xf0,
0x88,0xf0,0x88,0x88,0xf0,0x00,0x70,0x88,0x80,0x80,0x88,0x70,0x00,0xe0,0x90,0x88,
0x88,0x90,0xe0,0x00,0xf8,0x80,0xf0,0x80,0x80,0xf8,0x00,0xf8,0x80,0xf0,0x80,0x80,
0x80,0x00,0x70,0x88,0x80,0x98,0x88,0x70,0x00,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,
0x70,0x20,0x20,0x20,0x20,0x70,0x00,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x90,0xa0,
0xc0,0xa0,0x90,0x88,0x00,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x88,0xd8,0xa8,0x88,
0x88,0x88,0x00,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00,0x70,0x88,0x88,0x88,0x88,0x70,
0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x00,0x70,0x88,0x88,0xa8,0x98,0x70,0x00,0xf0,
0x88,0x88,0xf0,0x90,0x88,0x00,0x70,0x80,0x70,0x08,0x88,0x70,0x00,0xf8,0x20,0x20,
0x20,0x20,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x88,0x88,0x88,0x88,0x50,
0x20,0x00,0x88,0x88,0x88,0xa8,0xa8,0x50,0x00,0x88,0x50,0x20,0x20,0x50,0x88,0x00,
0x88,0x50,0x20,0x20,0x20,0x20,0x00,0xf8,0x10,0x20,0x40,0x80,0xf8,0x00,0x60,0x40,
0x40,0x40,0x40,0x60,0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x30,0x10,0x10,0x10,
0x10,0x30,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
0x00,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8};
/**************************************************************************
* put_char *
* Print char *
**************************************************************************/
void put_char(int x ,int y,int ascii_char ,byte color){
__asm__(
"push %si\n\t"
"push %di\n\t"
"push %cx\n\t"
"mov color,%dl\n\t" //test color
"mov ascii_char,%al\n\t" //test char
"sub $32,%al\n\t"
"mov $7,%ah\n\t"
"mul %ah\n\t"
"lea $characters,%si\n\t" …Run Code Online (Sandbox Code Playgroud) 对于乘法大二进制矩阵(10Kx20K),我通常要做的是将矩阵转换为浮点数并执行浮点矩阵乘法,因为整数矩阵乘法非常慢(请看这里).
但这一次,我需要执行超过数十万次这样的乘法运算,甚至平均事情上的毫秒级性能提升.
我想要一个int或float矩阵作为结果,因为产品可能有非0或1的元素.输入矩阵元素都是0或1,因此它们可以存储为单个位.
在行向量和列向量之间的内积中(为了产生输出矩阵的一个元素),乘法简化为按位AND.添加仍然是添加,但我们可以添加具有填充计数功能的位,而不是单独循环它们.
一些其他布尔/二进制矩阵函数或位而不是计数它们,产生位矩阵结果,但这不是我需要的.
下面是一个示例代码,显示将问题形成为std::bitset, AND并且count操作比矩阵乘法更快.
#include <iostream>
using std::cout; using std::endl;
#include <vector>
using std::vector;
#include <chrono>
#include <Eigen/Dense>
using Eigen::Map; using Eigen::Matrix; using Eigen::MatrixXf;
#include <random>
using std::random_device; using std::mt19937; using std::uniform_int_distribution;
#include <bitset>
using std::bitset;
using std::floor;
const int NROW = 1000;
const int NCOL = 20000;
const float DENSITY = 0.4;
const float DENOMINATOR = 10.0 - (10*DENSITY);
void fill_random(vector<float>& vec) { …Run Code Online (Sandbox Code Playgroud) 我希望能够手动预测任意算术的长度(即没有分支或内存,尽管这也很好)x86-64汇编代码将采用特定的体系结构,考虑到指令重新排序,超标量,延迟,消费者价格指数等
什么/描述必须遵循的规则才能实现这一目标?
我想我已经找到了一些初步规则,但是我没有找到任何关于将任何示例代码分解为这个详细程度的引用,所以我不得不做一些猜测.(例如,英特尔优化手册甚至几乎没有提到指令重新排序.)
至少,我正在寻找(1)确认每条规则是正确的,或者是每条规则的正确陈述,以及(2)我可能忘记的任何规则的列表.
addps并且subps使用相同的功能) unit?我如何确定?).和:4此循环已经发出少于超标量宽度(通常)指令的数量.例如,请考虑以下示例代码(计算交叉产品):
shufps xmm3, xmm2, 210
shufps xmm0, xmm1, 201
shufps xmm2, xmm2, 201
mulps xmm0, xmm3
shufps xmm1, xmm1, 210
mulps xmm1, xmm2
subps xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)
我试图预测Haswell的延迟看起来像这样:
; `mulps` Haswell latency=5, CPI=0.5
; `shufps` Haswell latency=1, CPI=1
; `subps` Haswell latency=3, CPI=1
shufps xmm3, xmm2, 210 ; cycle 1
shufps xmm0, xmm1, 201 ; cycle 2
shufps xmm2, xmm2, 201 ; …Run Code Online (Sandbox Code Playgroud) void swap(int* a, int* b) {
if (a != b)
*a ^= *b ^= *a ^= *b;
}
Run Code Online (Sandbox Code Playgroud)
由于以上*a ^= *b ^= *a ^= *b只是一个快捷方式*a = *a ^ (*b = *b ^ (*a = *a ^ *b)),可以(例如)第二个*a被评估(对于XOR)就在第三个*a被修改之前(由=)?
我是否用C99/C11/C++ 98/C++ 11编写它是否重要?
我有一个包含 4 个 long 的数组,我想计算给定范围内设置位的数量。这是我目前正在使用的函数(其中bitcount(uint64_t)是一个内联 asm 函数,它给出了参数中设置的位数):
unsigned count_bits(const uint64_t *long_ptr, size_t begin, size_t end)
{
uint64_t start_mask = ~((1L << (begin & 63)) - 1);
uint64_t end_mask = ((1L << (end & 63)) - 1);
if (begin >= 0 && begin < 64) {
if (end < 64) {
return bitcount(long_ptr[0] & start_mask & end_mask);
} else if (end < 128) {
return bitcount(long_ptr[0] & start_mask) + bitcount(long_ptr[1] & end_mask);
} else if (end < 192) { …Run Code Online (Sandbox Code Playgroud) 我有一个任务,除其他外,我需要在.asm文件中查找某个指令和"反向工程"(找出)C代码的哪一部分导致它在汇编程序级别执行.(文字下方的例子)
什么是最快(最简单)的方法.或者更好地说,.asm文件中的其他命令/指令/标签应该/我可以注意什么,这将指导我使用正确的C代码?
我几乎没有使用汇编代码的经验,很难弄清楚C代码的确切行会导致特定指令发生.
如果这有任何区别,那么这个架构就是TriCore.
示例:通过跟踪使用变量的位置,我设法找出C代码在asm文件中导致插入的内容
.L23:
movh.a a15,#@his(InsertStruct)
ld.bu d15,[a15]@los(InsertStruct)
or d15,#1
st.b [a15]@los(InsertStruct),d15
.L51:
ld.bu d15,[a15]@los(InsertStruct)
insert d15,d15,#0,#0,#1
st.b [a15]@los(InsertStruct),d15
.L17:
mov d15,#-1
Run Code Online (Sandbox Code Playgroud)
这导致我得到以下C代码:
InsertStruct.SomeMember = 0x1u;
InsertStruct.SomeMember = 0x0u;
Run Code Online (Sandbox Code Playgroud) 当我尝试研究内核的系统调用的返回值时,我找到了描述它们的表,以及我需要将它放在不同的寄存器中以使它们工作.但是,我没有找到任何文档说明我从系统调用获得的返回值是什么.我只是在不同的地方找到我收到的东西将在EAX寄存器中.
结果通常在EAX寄存器中返回.
汇编语言循序渐进: Jeff Duntemann 编写的Linux书籍在他的程序中多次说明:
查看sys_read在EAX中的返回值
复制sys_read返回值以便安全保存
我没有解释任何有关此返回值的网站.有没有互联网资源?或者有人能解释我这个价值观吗?