相关疑难解决方法(0)

为什么参数存储在寄存器中而不是存储在x86-64汇编中的堆栈中?

在x86-32汇编中,参数存储在堆栈中,但在x86-64中,参数存储在寄存器中.这是什么原因?

assembly x86-64 function-parameter

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

调用约定有何不同?

据我所知,调用约定取决于平台是Windows还是Linux。

我想知道,

  1. 编译器使调用约定不同。
  2. 平台使调用约定有所不同。

哪一个是真的?如果只有 2 为真,则调用约定是由平台定义的,编译器是否只遵循定义的约定?

c++ assembly abi calling-convention

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

C++ 文件无法识别汇编文件中定义的函数

我正在尝试学习一些汇编代码,并且正在遵循一本书提出的教程,我的 C++ 代码定义如下(Ch02_01.cpp):

#include <iostream>


using namespace std;

extern "C" int IntegerAddSub_(int a, int b, int c, int d);
int main() {
    int a, b, c, d, result;
    a = 101;  b = 34; c = -190; d = 25;
    result = IntegerAddSub_(a, b, c, d);
    cout << "result = " << result << n1;
    return 0;
}

Run Code Online (Sandbox Code Playgroud)

知道函数 IntegerAddSub_ 是在文件夹中的汇编文件(扩展名为 asm)中定义的,如下(Ch02_01.asm):

; extern "C" int IntegerAddSub_(int a, int b, int c, int d);

        .code
IntegerAddSub_ proc
; Calculate a …
Run Code Online (Sandbox Code Playgroud)

c++ assembly g++ nasm

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

在 C 函数调用之前,以任何方式(跨编译器、平台、libc 实现等)PUSH 内联汇编中的额外参数是否安全或可移植?

我写了一个函数来漂亮地打印一个数独,当然这个模式可以由一些循环生成,但我不想经历麻烦,所以这就是我想出的(前 5 个格式说明符只是参数) printf 本身被压入堆栈,并且在回车后将被覆盖)。

\n

虽然“它可以在我的机器上运行”,但我想知道这是否可以或可以移植到跨架构、编译器、libc 实现等工作?

\n

当然,根据目标平台,汇编代码可能需要进行一些调整,并且 printf 推送的参数数量取决于当前的 libc 实现。

\n
#define PUSH(x) asm volatile ("push %0" : : "m"(x) :)\n#define POP() asm volatile ("pop %%rax" : : : "rax")\n\nvoid print(void) {\n    for (uint8_t i = 1; i <= (9 * 9); ++i) {\n        PUSH(sudoku[(9 * 9) - i]);\n    }\n\n    printf("%hhd%hhd%hhd%hhd%hhd\\r\xe2\x95\x94\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x97\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91\\n"\n           "\xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd \xe2\x95\x91 %hhd  %hhd  %hhd …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc x86-64 inline-assembly

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

汇编 - 将参数传递给函数调用

我目前正在通过反汇编C程序并试图了解它们的作用来进行汇编阅读.

我被困在一个简单的问题:一个简单的你好世界计划.

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

int main() {
  printf("Hello, world!");
  return(0);
}
Run Code Online (Sandbox Code Playgroud)

当我拆卸主要时:

(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000400526 <+0>: push   rbp
   0x0000000000400527 <+1>: mov    rbp,rsp
   0x000000000040052a <+4>: mov    edi,0x4005c4
   0x000000000040052f <+9>: mov    eax,0x0
   0x0000000000400534 <+14>:    call   0x400400 <printf@plt>
   0x0000000000400539 <+19>:    mov    eax,0x0  
   0x000000000040053e <+24>:    pop    rbp
   0x000000000040053f <+25>:    ret
Run Code Online (Sandbox Code Playgroud)

我理解前两行:基本指针保存在堆栈上(通过push rbp,这会导致堆栈指针的值减少8,因为它已经"增长")并且堆栈指针的值被保存在基指针中(这样,参数和局部变量可以分别通过正偏移和负偏移轻松到达,而堆栈可以保持"增长").

第三行提出了第一个问题:为什么0x4005c4("Hello,World!"字符串的地址)在edi寄存器中移动而不是在堆栈中移动?printf函数不应该将该字符串的地址作为参数吗?据我所知,函数从堆栈中获取参数(但在这里,看起来参数放在该寄存器中:edi)

在StackOverflow上的另一篇文章中,我读到"printf @ ptl"就像一个调用真正的printf函数的存根函数.我试图反汇编这个功能,但它变得更加混乱:

(gdb) disassemble printf
Dump of assembler code for function __printf:
   0x00007ffff7a637b0 <+0>: sub    rsp,0xd8
   0x00007ffff7a637b7 <+7>: test   al,al …
Run Code Online (Sandbox Code Playgroud)

linux assembly x86-64 abi calling-convention

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

OsDev系统调用/ sysret和sysenter/sysexit指令启用

我正在组装中构建一个32位操作系统.
我已经设置了IDT,我正在通过int指令处理程序interruptus .

如何启用syscallsysenter说明以及如何处理/返回?
诚然,syscall指令在32位基于英特尔处理器的支持,所以我不能用它?sysret教学不安全是真的吗?在某处存在一个教程吗?

编辑:我的主要问题是如何启用syscallsysenter说明!(没有重复)

assembly system-calls protected-mode osdev interrupt-handling

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

为什么x86-64 System V调用约定在寄存器而不是堆栈中传递args?

为什么32位C将所有函数参数直接推送到堆栈上,而64位C将前6个参数放入寄存器而其余的放在堆栈中?

所以32位堆栈看起来像:

...
arg2
arg1
return address
old %rbp
Run Code Online (Sandbox Code Playgroud)

虽然64位堆栈看起来像:

...
arg8
arg7
return address
old %rbp
arg6
arg5
arg4
arg3
arg2
arg1
Run Code Online (Sandbox Code Playgroud)

那么为什么64位C会这样做呢?将所有内容都推送到堆栈而不是将前6个参数放在寄存器中以便将它们移动到函数序言中的堆栈中是不是更容易?

assembly gcc x86-64 calling-convention

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

段寄存器如何参与内存地址转换?

在我迄今为止学到的关于分割的内容中:

  • 虚拟地址包含段选择器和偏移量
  • 段选择器与GDTR结合使用以查找段描述符的线性地址
  • 段描述符包含有关所选段的信息,包括其线性地址

所以,我的问题是:

  • 基于我所读到的内容,虚拟地址被加载到段寄存器中,然后以某种方式从那里继续转换.在将虚拟地址加载到其中以获取描述符后,段寄存器会发生什么?

  • 据我了解,段寄存器还包含描述符的缓存值.这在翻译过程中如何发挥作用?

  • 系统如何确定要加载哪个段寄存器,假设段选择器最多可以有2 ^ 13个不同的值且只有6个主寄存器?

hardware x86 x86-64 intel cpu-registers

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

如何将C中的NULL推入汇编中的堆栈?

我正在用汇编语言编写用于冒泡排序的冒泡排序,并且正在使用strtok()对字符串进行标记化。但是,在第一次调用strtok(str,“”)之后,我需要将NULL作为参数传递,即strtok(NULL,“”)

我已经在.bss段中尝试了NULL equ 0,但这没有任何作用。

[SECTION .data]

[SECTION .bss]

string resb 64
NULL equ 0

[SECTION .text]

extern fscanf
extern stdin
extern strtok

global main

main:

    push ebp        ; Set up stack frame for debugger
    mov ebp,esp
    push ebx        ; Program must preserve ebp, ebx, esi, & edi
    push esi
    push edi

    push cadena
    push frmt
    push dword [stdin]      ;Read string from stdin
    call fscanf
    add esp,12              ;clean stack

    push delim
    push string             ;this works
    call strtok
    add esp,8               ;clean stack …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly nasm

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