在线程中使用__asm {}代码是危险的吗?
例如,我在一个核心上运行了2个线程,在另一个核心上运行了main().如果一个线程在eax上写入并读取ebx而另一个线程读取eax并在ebx上写入会发生什么?如果我从main()读取这些寄存器会发生什么?
我正在尝试使用内联汇编的示例:http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html 但是有些事让我感到困惑:
"好吧,当GCC能够确切地知道你之前和之后对寄存器做了什么时,这确实很有帮助......如果你告诉它将(x + 1)放入寄存器中,它甚至足够聪明. ,如果你没有破坏它,后来C代码引用(x + 1),并且它能够保持该寄存器空闲,它将重用计算.哇."
关于clobber列表的教程中存在一些不一致:
对于输入/输出列表中指定的寄存器,不需要将它们放入clobber列表中,因为GCC知道; 但是在关于rep_movsl(或rep_stosl)的示例中:
asm("cld \n\t""rep \n\t""stosl":/*无输出寄存器*/:"c"(计数),"a"(fill_value),"D"(dest):" %ecx","%edi");
虽然"S,D,c"在输出操作数中,但它们再次被列为破坏.我在C中尝试了一个简单的片段:
#include<stdio.h>
int main()
{
int a[] = {2, 4, 6};
int b[3];
int n = 3;
int v = 12;
asm ("cld\n\t"
"rep\n\t"
"movsl"
:
: "S" (a), "D" (b), "c" (n)
: );
// : "%ecx", "%esi", "%edi" );
printf("%d\n", b[1]);
}
Run Code Online (Sandbox Code Playgroud)
如果我使用评论的clobber列表,GCC会抱怨:
ac:8:3:错误:在重新加载'asm'ac时,无法在类'CREG'中找到寄存器:8:3:错误:'asm'操作数有不可能的约束
如果我使用空的clobber列表,它将编译并输出为4.
我是软件故障注入领域的新研究员,目前我的最终目标是编写一段简单的代码,能够更改 CPU 寄存器中的单个位。我想用 C 来做(在代码中包含一些程序集调用)。考虑到这一点,我在 Stack Overflow 中找到了这个关于如何访问 32 位 CPU 寄存器内容的好线程和简单示例:Is it possible to access 32-bit registers in C? 通过这种方式,我能够编写这个简单的代码:
#include <stdio.h>
int main()
{
register int value;
register int ecx asm("ecx");
printf("Contents of ecx: %d\n", ecx);
asm("movl %%ecx, %0;" : "=r" (value) : ); //Assembly: this stores the ecx value into the variable value
printf("Contents of value: %d\n", value);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这似乎是对这个主题的一个很好的介绍,那里提供的答案给了我很好的洞察力和信息来源(我已经在阅读 GCC 文档),但现在我需要更进一步,即,我需要了解如何才能我更改了 CPU 寄存器中单个位的内容(或者至少,首先,更简单的事情:如何更改 CPU 寄存器值?)。如果有人能给我一个提示或告诉我寻找它的最合适的来源,我将不胜感激。
祝一切顺利,提前致谢,若昂
PS:不知道这是否有帮助,但我正在使用 CentOS 6.5 32 位系统(尽管 CPU 是 …
我有以下功能,需要使其与64位平台兼容:
procedure ExecuteAsm(Tab, Buf: Pointer; Len: DWORD);
asm
mov ebx, Tab
mov ecx, Len
mov edx, Buf
@1: mov al, [edx]
xlat
mov [edx], al
inc edx
dec ecx
jnz @1
end;
Run Code Online (Sandbox Code Playgroud)
Delphi XE5 [dcc64 Error] E2107 Operand size mismatch在带有Tab和Len参数的行上引起错误.
不幸的是,我不知道汇编程序是否足以自行解决问题.成功编译函数应该更改什么?
在linux内核中,您可以找到如下组件:
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
Run Code Online (Sandbox Code Playgroud)
当像这样使用时
DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
Run Code Online (Sandbox Code Playgroud)
生成以下程序集
->NR_PAGEFLAGS $24 __NR_PAGEFLAGS
Run Code Online (Sandbox Code Playgroud)
这显然是有效的集会.这是做什么的?
这个asm如何定义一个变量?请指出任何更详细解释这一点的文档.谢谢!
我在文本模式下更新光标位置的函数有问题,函数定义和声明是
#include <sys/io.h>
signed int VGAx = 0,VGAy=0;
void setcursor()
{
uint16_t position = VGAx+VGAy*COLS;
outb(0x0f, 0x03d4);
outb((position<<8)>>8,0x03d5);
outb(0x0e,0x03d4);
outb(position>>8,0x03d5);
}
Run Code Online (Sandbox Code Playgroud)
和文件 sys/io.h
static inline unsigned char inb (unsigned short int port)
{
unsigned char value;
asm ("inb %0, %%al":"=rm"(value):"a"(port));
return value;
}
static inline void outb(unsigned char value, unsigned short int port)
{
asm volatile ("outb %%al, $0"::"rm"(value), "a"(port));
}
Run Code Online (Sandbox Code Playgroud)
使用该功能前光标有时闪烁下划线有时不出现而使用该功能后没有光标出现
这是运行的主要功能
#include <vga/vga.h>
int kmain(){
setcursor()
setbgcolor(BLACK);
clc();
setforecolor(BLUE);
terminal_write('h');
setcursor();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用此功能
void enable_cursor() { …Run Code Online (Sandbox Code Playgroud) 我正在关注youtube上的一个教程,他说需要在C中编写一些asm代码(我在汇编方面不是很好)所以我只是处理了整个代码:
unsigned char inPortB (unsigned int _port) {
unsigned char rv;
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
return rv;
}
Run Code Online (Sandbox Code Playgroud)
和
void outPortB (unsigned int _port, unsigned char _data) {
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}
Run Code Online (Sandbox Code Playgroud)
但是当我编译我得到这个错误:
operand type mismatch for 'in'
operand type mismatch for 'out'
Run Code Online (Sandbox Code Playgroud)
我该怎么办呢?
我在由g ++(7.3.0)编译的内联汇编中使用“ shld”指令。它产生一些奇怪的结果。
在Ubuntu和WSL上尝试过。
unsigned long long hi, lo;
//some code goes here
//...
asm volatile (
"shld $0x3, %1, %0;\n"
: "=r"(hi)
: "r"(lo)
:
);
//I expect the asm produces this:
//hi = (hi << 3) | (lo >> 61);
//but the actual result is:
//hi = (lo << 3) | (lo >> 61);
//you can see the real assembly produced by gcc below.
Run Code Online (Sandbox Code Playgroud)
我希望“ hi”中的结果值为
(hi << 3) | (lo >> 61)
Run Code Online (Sandbox Code Playgroud)
但是实际结果是
(lo << 3) | …Run Code Online (Sandbox Code Playgroud) 我发现可能是通过SGDT汇编命令读取GDTR。我将这段程序集插入我的C代码中Error: operand type mismatch for 'sgdt'
unsigned long j;
asm("sgdt %0" : "=r"(j));
Run Code Online (Sandbox Code Playgroud) 我想使用C语言中的扩展asm来处理syscall(写)。一切都很好,我正在使用
#define write(RESULT, FD, BUFF, SIZE) \
asm volatile ("syscall" : \
"=a" (RESULT) : \
"D" (FD), "S" (BUFF), "d" (SIZE), "a" (1))
Run Code Online (Sandbox Code Playgroud)
这没有任何问题...例如
#define write(RESULT, FD, BUFF, SIZE) \
asm volatile ("syscall" : \
"=a" (RESULT) : \
"D" (FD), "S" (BUFF), "d" (SIZE), "a" (1))
int
main() {
int res;
write(res, 1, "Hello\n", 6);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我对此代码没有问题,但是我的问题是当我拨打此电话时
write(res, 1, "Hello\n", 6);
Run Code Online (Sandbox Code Playgroud)
循环使用100次
#define write(RESULT, FD, BUFF, SIZE) \
asm volatile ("syscall" : \
"=a" (RESULT) : …Run Code Online (Sandbox Code Playgroud)