背景:我的任务是为Unitech HT630编写一个数据收集程序,它运行一个专有的DOS操作系统,可以运行为16位MS DOS编译的可执行文件,尽管有一些限制.我正在使用Digital Mars C/C++编译器,它似乎运行得很好.
对于某些我可以使用标准C库的东西,但是在单元的屏幕上绘制等其他东西需要汇编代码.设备文档中给出的汇编示例与我在C/C++中使用内联汇编代码的方式不同.作为参考,BYTE在以下示例中是类型unsigned char.
给出了示例代码的示例:
#include <dos.h>
/* Set the state of a pixel */
void LCD_setpixel(BYTE x, BYTE y, BYTE status) {
if(status > 1 || x > 63 || y > 127) {
/* out of range, return */
return;
}
/* good data, set the pixel */
union REGS regs;
regs.h.ah = 0x41;
regs.h.al = status;
regs.h.dh = x;
regs.h.dl = y;
int86(0x10, ®s, ®s);
}
Run Code Online (Sandbox Code Playgroud)
我如何被教导使用内联汇编:
/* …Run Code Online (Sandbox Code Playgroud) 我用devcpp和borland c编译器....
asm {
mov ax,4 // (I/O Func.)
mov bx,1 // (Output func)
mov cx,&name // (address of the string)
mov dx,6 // (length of the string)
int 0x21 // system call
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,我想在汇编语言的帮助下打印一个字符串...但是如何将字符串的地址放在寄存器cx ....
代码中有什么问题???
在我目前的项目中,我必须比较128位值(实际上是md5哈希),我认为可以通过使用SSE指令来加速比较.我的问题是我无法找到关于SSE指令的好文档; 我正在寻找一个128位整数比较指令,让我知道一个散列是大于,小于或等于另一个.这样的指令是否存在?
PS:目标计算机是带有SSE2指令的x86_64服务器; 我也对同一工作的NEON指令感兴趣.
我目前正在尝试为我的图书馆创建高度优化,可重复使用的功能.例如,我通过以下方式编写函数"is power of 2":
template<class IntType>
inline bool is_power_of_two( const IntType x )
{
return (x != 0) && ((x & (x - 1)) == 0);
}
Run Code Online (Sandbox Code Playgroud)
这是一个可移植,低维护的实现,作为内联C++模板.此代码由VC++ 2008编译为具有分支的以下代码:
is_power_of_two PROC
test rcx, rcx
je SHORT $LN3@is_power_o
lea rax, QWORD PTR [rcx-1]
test rax, rcx
jne SHORT $LN3@is_power_o
mov al, 1
ret 0
$LN3@is_power_o:
xor al, al
ret 0
is_power_of_two ENDP
Run Code Online (Sandbox Code Playgroud)
我从这里找到了实现:"bit twiddler",它将在x64的程序集中编码,如下所示:
is_power_of_two_fast PROC
test rcx, rcx
je SHORT NotAPowerOfTwo
lea rax, [rcx-1]
and rax, …Run Code Online (Sandbox Code Playgroud) Metro Windows 8应用程序可以包含内联汇编程序吗?也是Metro C++ Native,或托管,或者你可以像C++/CLI一样混合它们吗?
c++ inline-assembly microsoft-metro windows-8 windows-runtime
我正在学习x86内联汇编编程.
我想写mov ecx, FFFFFFBB,但编译器没有认识到它.这样的十六进制数应该如何用内联汇编代码编写?
如果我想向程序员公开一个特定于机器的指令,我有两种方法可以这样做:
我已经读过内置函数允许编译器处理类型检查,寄存器分配和"其他优化"等.但是即使在asm()的情况下,编译器也需要这样做,对吧?那么对于单个指令使用asm()内在的性能优势究竟是什么呢?
如果涉及多个机器指令,方程式如何变化?
支持内在的"可移植性"论证是可以理解的,但我很想知道其中一个的性能优势(如果有的话).
所以我在一段时间后自学了x86程序集,只是在C++中使用内联汇编.
所以我想做的是在函数参数,传入数组,索引(unsigned int)和数字.使用程序集,它会将数组的内存位置中的值更改为传入的值.所以代码看起来像这样.
inline void Set( int pArray[], unsigned int pIndex, int pNum ) {
__asm {
mov ebx, pIndex
mov eax, 4
mul ebx
mov ebx, pNum
lea edi, pArray
mov [ edi + eax ], ebx
}
}
int main() {
int myArray[ 5 ] = { 1, 2, 3, 4, 5 };
Set( myArray, 2, 7 );
std::cout << myArray[ 2 ] << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
所以代码应该加载数组地址的开头,获取索引并将其乘以4,以便内存位置移动那么多字节,然后将其更改为传入的值.但是,当我这样做时,值保持不变.这是为什么?出了什么问题?
我有以下使用内联汇编的函数,目标mipsel-unknown-linux-gnu:
#![feature(asm)]
#[no_mangle]
pub unsafe extern "C" fn f(ptr: u32) {
let value: i8;
asm!(
"lb $v0, ($a0)",
in("$4") ptr,
out("$2") value,
);
asm!(
"sb $v0, ($a0)",
in("$4") ptr,
in("$2") value,
);
}
Run Code Online (Sandbox Code Playgroud)
我预计这会编译成以下内容:
lb $v0, ($a0)
sb $v0, ($a0)
jr $ra
nop
Run Code Online (Sandbox Code Playgroud)
注意:在此示例中,编译器可能会在跳转后将存储指令重新排序以使用延迟槽,但在我的实际用例中,我通过块返回asm,因此不必担心。鉴于此,我完全预料到了上面的装配。
相反,我得到的是:
00000000 <f>:
0: 80820000 lb v0,0(a0)
4: 304200ff andi v0,v0,0xff
8: a0820000 sb v0,0(a0)
c: 03e00008 jr ra
10: 00000000 nop
Run Code Online (Sandbox Code Playgroud)
编译器似乎不相信我的输出是 ani8并andi $v0, 0xff在那里插入了一条指令。
我需要准确地生成上面指定的程序集,因此我想删除该andi …
受到最近一个问题的启发。
gcc 式内联汇编的一种用例是对编译器和汇编器都不知道的指令进行编码。例如,我给出了如何在太旧而无法支持的工具链上使用指令的示例:rdrand
/* "rdrand %%rax ; setc %b1" */
asm volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %b1"
: "=a"(result), "=qm"(success) :: "cc");
Run Code Online (Sandbox Code Playgroud)
不幸的是,对指令进行硬编码意味着您还需要对其使用的寄存器进行硬编码,从而大大减少了编译器执行寄存器分配的自由度。
在某些架构上(例如带有.insn指令的 RISC-V),汇编器提供了一种系统地构建原始指令的方法,但这似乎是例外。
一个简单的解决方案是有一种方法来获取寄存器的未修饰编号,以将其手动编码到指令中。例如,假设X存在模板修饰符来打印所选寄存器的编号。那么,上面的例子可以变得更加灵活:
/* "rdrand %0 ; setc %b1" */
asm volatile (".byte 0x48 | (%X0 >> 3), 0x0f, 0xc7, 0xf0 | (%X0 & 7); setc %b1"
: "=r"(result), "=qm"(success) :: "cc");
Run Code Online (Sandbox Code Playgroud)
同样,如果有一种方法可以让 gcc 打印12而不是v12ARM64 上的 SIMD 寄存器 12,则可以执行如下操作:
float32x4_t add3(float32x4_t a, float32x4_t b) …Run Code Online (Sandbox Code Playgroud)