相关疑难解决方法(0)

在intel 64bit机器上启用/禁用缓存:CD位总是设置?

我正在尝试在Xen中禁用我的机器Intel(R)Xeon(R)CPU E5-1650 v2 @ 3.50GHz的所有级别的缓存.我编写了一个工具来调用以下汇编代码来禁用/启用缓存并显示CR0寄存器的值.

case XENMEM_disable_cache:
    __asm__ __volatile__(
        "pushq %%rax\n\t"
        "movq %%cr0,%%rax\n\t"
        "orq $0x40000000,%%rax\n\t"
        "movq %%rax,%%cr0\n\t"
        "movq %%cr0, %0\n\t"
        "wbinvd\n\t"
        "popq  %%rax"
        : "=r"(cr0)
        :
        :);
    // gdprintk(XENLOG_WARNING, "gdprintk:XENMEM_disable_cache disable cache!
    // TODO IMPLEMENT\n");
    printk("<1>printk: disable cache! cr0=%#018lx\n", cr0);
    rc = 0;
    break;

case XENMEM_enable_cache:
    __asm__ __volatile__(
        "pushq %%rax\n\t"
        "movq %%cr0,%%rax\n\t"
        "andq $0xffffffffbfffffff,%%rax\n\t" /*~0x4000000*/
        "movq %%rax,%%cr0\n\t"
        "movq %%cr0, %0\n\t"
        "popq  %%rax"
        : "=r"(cr0)
        :
        :);
    printk("<1>printk: enable cache; cr0=%#018lx\n", cr0);
    rc = 0;
    break;

case XENMEM_show_cache:
    __asm__ __volatile__(
        "pushq …
Run Code Online (Sandbox Code Playgroud)

c assembly kernel linux-kernel

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

使用GNU C内联汇编在VGA内存中绘制字符

我正在学习用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)

c x86 gcc dos djgpp

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

英特尔的时间戳读取asm代码示例是否使用了两个以上的寄存器?

我正在研究使用x86 CPU中的时间戳寄存器(TSR)来测量基准性能.它是一个有用的寄存器,因为它以单调时间单位测量,不受时钟速度变化的影响.很酷.

这是一份英特尔文档,显示了使用TSR进行可靠基准测试的asm片段,包括使用cpuid进行管道同步.见第16页:

http://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html

要读取开始时间,它说(我注释了一下):

__asm volatile (
    "cpuid\n\t"             // writes e[abcd]x
    "rdtsc\n\t"             // writes edx, eax
    "mov %%edx, %0\n\t" 
    "mov %%eax, %1\n\t"
    //
    :"=r" (cycles_high), "=r" (cycles_low)  // outputs
    :                                       // inputs
    :"%rax", "%rbx", "%rcx", "%rdx");       // clobber
Run Code Online (Sandbox Code Playgroud)

我不知道为什么暂存寄存器用来取的价值观edxeax.为什么不删除MOVS和读取TSR值右出的edxeax?像这样:

__asm volatile(                                                             
    "cpuid\n\t"
    "rdtsc\n\t"
    //
    : "=d" (cycles_high), "=a" (cycles_low) // outputs
    :                                       // inputs
    : "%rbx", "%rcx");                      // clobber     
Run Code Online (Sandbox Code Playgroud)

通过这样做,您可以保存两个寄存器,从而降低C编译器需要溢出的可能性.

我对吗?或者那些MOV在某种程度上是战略性的?

(我同意你确实需要临时寄存器来读取停止时间,因为在那种情况下指令的顺序是相反的:你有rdtscp,...,cpuid.cpuid指令破坏了rdtscp的结果).

谢谢

c benchmarking assembly inline-assembly rdtsc

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

我如何告诉 gcc 我的内联汇编破坏了堆栈的一部分?

考虑这样的内联汇编:

uint64_t flags;
asm ("pushf\n\tpop %0" : "=rm"(flags) : : /* ??? */);
Run Code Online (Sandbox Code Playgroud)

尽管可能存在某种内在函数来获取 RFLAGS 的内容,但我如何向编译器表明我的内联汇编破坏了堆栈顶部的一个四字内存?

c gcc x86-64 inline-assembly red-zone

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

x86_64:是否可以"在线替代"PLT/GOT参考?

我不确定这个问题的主题是什么,但是我们走了......

为了强制代码的关键部分的代码局部性/紧凑性,我正在寻找一种方法在调用时R_X86_64_JUMP_SLOT直接通过"跳槽"(ELF 重定位)在外部(动态加载)库中调用函数site - 链接器通常放入PLT/GOT的内容,但是在调用站点上有这些内联.

如果我模仿这样的调用:

#include <stdio.h>
int main(int argc, char **argv)
{
        asm ("push $1f\n\t"
             "jmp *0f\n\t"
             "0: .quad %P0\n"
             "1:\n\t"
             : : "i"(printf), "D"("Hello, World!\n"));
        return 0;
}
Run Code Online (Sandbox Code Playgroud) 为了得到一个64位字的空间,电话本身是有效的(拜托,没有评论这是幸运的巧合,因为这打破了某些ABI规则 - 所有这些都不是这个问题的主题......并且,对于我的情况,可以工作围绕/以其他方式解决,我试图保持这个例子简短).

它创建以下程序集:

0000000000000000 <main>:
   0:   bf 00 00 00 00          mov    $0x0,%edi
                        1: R_X86_64_32  .rodata.str1.1
   5:   68 00 00 00 00          pushq  $0x0
                        6: R_X86_64_32  .text+0x19
   a:   ff 24 25 00 00 00 00    jmpq   *0x0
                        d: R_X86_64_32S .text+0x11
        ...
                        11: R_X86_64_64 printf
  19:   31 …

assembly gcc x86-64 elf ld

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

从c调用汇编函数

我试图从c调用汇编函数,但我不断收到错误.

    .text
    .globl integrate
    .type integrate, @function
integrate:
    push %ebp
    mov %esp, %ebp
    mov $0,%edi
start_loop:                
    cmp %edi,1024           
    je loop_exit
    mov 8(%ebp),%eax          
    mov 12(%ebp),%ecx          
    sub %eax,%ecx              
    add %edi,%ecx
    incl %edi                
    jmp start_loop             
loop_exit:                 
    movl %ebp, %esp
    popl %ebp
    ret   
Run Code Online (Sandbox Code Playgroud)

这是我的汇编函数,名为integrate.s的文件.

#include <stdio.h>

extern int integrate(int from,int to);

void main()
{
    printf("%d",integrate(1,10));
}
Run Code Online (Sandbox Code Playgroud)

继承人我的代码.

function.c:5:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
/tmp/cciR63og.o: In function `main':
function.c:(.text+0x19): undefined reference to `integrate'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

每当我尝试使用gcc -Wall …

c x86 assembly inline-assembly

6
推荐指数
4
解决办法
3万
查看次数

我可以在同一行上写多个汇编指令吗?

我可以在同一行上编写多个汇编指令,就像使用大多数高级语言一样.或者每个汇编程序是否以不同方式处理此功能?

assembly

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

警告#13212:在需要堆栈对齐的函数中引用ebx

我正在尝试使用ICC 2018编译以下代码:

__asm {
        mov ebx, xx              ;xx address to registers
}
Run Code Online (Sandbox Code Playgroud)

其中xx的类型为int16.这是我函数中的第一条指令.

我使用上面的汇编代码得到以下警告:警告#13212:在需要堆栈对齐的函数中引用ebx

令人惊讶的是,当我用eax或esi替换ebx时,我看到警告消失了.我无法理解为什么我只看到ebx的问题,据我所知,ebx和eax都有相同的架构(32位寄存器).

此外,当我使用ICC 2013编译相同的代码时,我没有看到警告.

谁能帮我解决这个警告?

谢谢!

c++ assembly

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

使用内联汇编在数组上循环

当使用内联汇编循环数组时,我应该使用寄存器修饰符"r"还是内存修饰符"m"?

让我们考虑其将两个浮标阵为例x,与y和结果写入z.通常我会使用内在函数这样做

for(int i=0; i<n/4; i++) {
    __m128 x4 = _mm_load_ps(&x[4*i]);
    __m128 y4 = _mm_load_ps(&y[4*i]);
    __m128 s = _mm_add_ps(x4,y4);
    _mm_store_ps(&z[4*i], s);
}
Run Code Online (Sandbox Code Playgroud)

这是我使用寄存器修饰符"r"提出的内联汇编解决方案

void add_asm1(float *x, float *y, float *z, unsigned n) {
    for(int i=0; i<n; i+=4) {
        __asm__ __volatile__ (
            "movaps   (%1,%%rax,4), %%xmm0\n"
            "addps    (%2,%%rax,4), %%xmm0\n"
            "movaps   %%xmm0, (%0,%%rax,4)\n"
            :
            : "r" (z), "r" (y), "r" (x), "a" (i)
            :
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生与GCC类似的组装.主要区别在于GCC将16添加到索引寄存器并使用1的标度,而内联汇编解决方案将4添加到索引寄存器并使用4的标度.

我无法使用通用寄存器作为迭代器.在这种情况下,我必须指定一个rax.是否有一个原因?

这是我想出的使用内存修饰符"m"的解决方案

void add_asm2(float *x, float *y, …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc inline-assembly

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

当我命名寄存器时,为什么asm有不可能的限制?

我是C的装配新手,我不知道如何解决这个错误.我正在创建一个意味着写一个文件的函数.我有的是:

ssize_t mywrite(int fd, const void *buf, size_t count) {
//  return write(fd, buf, count);
    ssize_t var;
    __asm__("movl $4,%%eax\n\t"  // Write
        "movl %1,%%ebx\n\t"
        "movl %2,%%ecx\n\t"
        "movl %3,%%edx\n\t"
        "int  $0x80\n\t"         // System call
        "movl %%eax,%0"
        :"=r"(var)
        :"r"(fd),"r"(buf),"r"(count)
        :"%eax","%ebx","%ecx","%edx"
    );
    return var;
}
Run Code Online (Sandbox Code Playgroud)

我的asm应该和write一样(fd,buf,count); 当我编译它时,我得到''asm'操作数有不可能的限制".但是,如果不命名变量并直接从堆栈中获取值,则不会出现错误.这是代码

    __asm__("movl $4,%%eax\n\t"
        "movl 8(%%ebp),%%ebx\n\t"
        "movl 12(%%ebp),%%ecx\n\t"
        "movl 16(%%ebp),%%edx\n\t"
        "int  $0x80\n\t"
        "movl %%eax,%0"
        :"=r"(var)
        :
        :"%eax","%ebx","%ecx","%edx"
    );
Run Code Online (Sandbox Code Playgroud)

我可以使用第二个代码,ofc,但我需要用优化2编译它.然后%ebp将不会指向我需要的地方.我尝试使用"a","b","c"和"d"代替"r",但没有成功.有人可以帮忙吗?感谢:D

c assembly

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

标签 统计

assembly ×8

c ×7

gcc ×4

inline-assembly ×4

x86 ×2

x86-64 ×2

benchmarking ×1

c++ ×1

djgpp ×1

dos ×1

elf ×1

kernel ×1

ld ×1

linux-kernel ×1

rdtsc ×1

red-zone ×1