相关疑难解决方法(0)

使用C void参数"void foo(void)"或不使用"void foo()"更好吗?

什么是更好的:void foo()void foo(void)?随着虚空,它看起来丑陋和不一致,但我被告知它是好的.这是真的?

编辑:我知道一些旧的编译器做了奇怪的事情,但如果我只使用GCC,那void foo()好吗?将foo(bar);随后被接受?

c void

200
推荐指数
6
解决办法
10万
查看次数

132
推荐指数
4
解决办法
10万
查看次数

81
推荐指数
7
解决办法
8万
查看次数

如何在gcc中实现变量参数?

int max(int n, ...)
Run Code Online (Sandbox Code Playgroud)

我正在使用cdecl调用约定,其中调用者在被调用者返回后清理变量.

我想知道怎么做宏va_end,va_startva_arg工作?

调用者是否将参数数组的地址作为max的第二个参数传递?

c gcc variadic-functions calling-convention

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

如何在装配NASM中打印数字?

假设我在寄存器中有一个整数,我该如何打印?你能展示一个简单的示例代码吗?

我已经知道如何打印一个字符串,如"你好,世界".

我正在Linux上开发.

linux x86 assembly nasm

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

如何使用printf为64位Mac OS X编写汇编语言hello world程序?

我正在努力学习为64位Mac OS编写汇编语言.我对32位Mac OS以及32位和64位Linux没有任何问题.

但是,Mac OS 64位是不同的,我无法弄清楚.因此,我在这里寻求帮助.

我没有使用系统调用打印的问题.但是,我想学习如何使用Mac OS的64位汇编语言调用C函数.

请查看以下代码

.data
_hello:
    .asciz "Hello, world\n"


.text
.globl _main
_main:
    movq $0, %rax
    movq _hello(%rip), %rdi
    call _printf
Run Code Online (Sandbox Code Playgroud)

我使用$ gcc -arch x86_64 hello.s

组装和链接.

它生成二进制代码.但是,运行它时出现了分段错误.

我在调用_printf之前尝试添加"subq $ 8,%rsp",仍然和以前一样.

我做错了什么?

顺便说一下,这是在Mac上调试此代码的任何方法吗?我尝试添加-ggdb或-gstab或-gDWARF和$ gdb ./a.out,但无法查看代码并设置断点.

macos 64-bit assembly printf 32bit-64bit

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

vararg函数如何找出机器码中的参数数量?

printf这样的可变函数如何找出它们得到的参数数量?

显然,参数的数量不会作为(隐藏)参数传递(请参阅asm示例中的printf调用).

有什么诀窍?

assembly printf variadic abi calling-convention

11
推荐指数
4
解决办法
5285
查看次数

为什么 printf 仍然可以在 RAX 小于 XMM 寄存器中 FP 参数数量的情况下工作?

我正在关注Linux 64系统中的《开始x64汇编编程》一书。我正在使用 NASM 和 gcc。
在关于浮点运算的章节中,本书指定了以下用于添加 2 个浮点数的代码。在本书和其他在线资源中,我读到寄存器 RAX 根据调用约定指定要使用的 XMM 寄存器的数量。
书中的代码如下:

extern printf
section .data
num1        dq  9.0
num2        dq  73.0
fmt     db  "The numbers are %f and %f",10,0
f_sum       db  "%f + %f = %f",10,0

section .text
global main
main:
    push rbp
    mov rbp, rsp
printn:
    movsd xmm0, [num1]
    movsd xmm1, [num2]
    mov rdi, fmt
    mov rax, 2      ;for printf rax specifies amount of xmm registers
    call printf

sum:
    movsd xmm2, [num1]
    addsd xmm2, [num2]
printsum:
    movsd …
Run Code Online (Sandbox Code Playgroud)

linux assembly x86-64 nasm calling-convention

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

编译器将 printf 更改为 puts

考虑以下代码:

#include <stdio.h>

void foo() {
    printf("Hello world\n");
}

void bar() {
    printf("Hello world");
}
Run Code Online (Sandbox Code Playgroud)

这两个函数产生的程序集是:

.LC0:
        .string "Hello world"
foo():
        mov     edi, OFFSET FLAT:.LC0
        jmp     puts
bar():
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        jmp     printf

Run Code Online (Sandbox Code Playgroud)

现在我知道puts 和 printf之间的区别,但我发现这很有趣,因为 gcc 能够内省 const char* 并确定是调用 printf 还是 puts。

另一个有趣的事情是bar,编译器将返回寄存器 ( eax)清零,即使它是一个void函数。为什么它在那里而不是在里面foo

我假设编译器“内省了我的字符串”是否正确,或者对此有另一种解释?

c assembly gcc compiler-optimization

4
推荐指数
2
解决办法
231
查看次数

“sub $16, %rsp”指令的用途是什么?

让我们采用以下基本 C 函数及其生成的故意未优化的程序集:

int main() {
    int i = 4;
    return 3;
}
Run Code Online (Sandbox Code Playgroud)

它产生以下(未优化的)程序集,这对我来说都是有意义的:

main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $4, -4(%rbp)
        movl    $3, %eax
        popq    %rbp
        ret
Run Code Online (Sandbox Code Playgroud)

然而,当我添加一个函数调用时,有两条指令我不太明白:

void call() {};
int main() {
    int i = 4;
    call();
    return 3;
}
Run Code Online (Sandbox Code Playgroud)
main:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp     <-- why is it subtracting 16?
        movl    $4, -4(%rbp)
        movl    $0, %eax      <-- why is it first clearing the %eax register?
        call    call
        movl    $3, %eax
        leave …
Run Code Online (Sandbox Code Playgroud)

assembly gcc x86-64 calling-convention

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