相关疑难解决方法(0)

main()真的是一个C++程序的开始吗?

C++标准中的$ 3.6.1/1节,

程序应包含一个名为main的全局函数,它是程序的指定开始.

现在考虑这段代码,

int square(int i) { return i*i; }
int user_main()
{ 
    for ( int i = 0 ; i < 10 ; ++i )
           std::cout << square(i) << endl;
    return 0;
}
int main_ret= user_main();
int main() 
{
        return main_ret;
}
Run Code Online (Sandbox Code Playgroud)

此示例代码执行我打算执行的操作,即进入main()应该是程序"开始" 的函数之前打印从0到9的整数平方.

我还用-pedantic选项GCC 4.5.0 编译它.它没有错误,甚至没有警告!

所以我的问题是,

这段代码真的符合标准吗?

如果它符合标准,那么它是否会使标准所说的无效?main()不是这个计划的开始!user_main()在执行之前执行main().

我知道要初始化全局变量main_ret,use_main()首先执行,但这是完全不同的事情; 关键是,它确实使标准中的引用语句$ 3.6.1/1无效,因为main() …

c++ program-entry-point standards-compliance entry-point

130
推荐指数
6
解决办法
2万
查看次数

退出和退货有什么区别?

从C程序中的任何地方调用时,C编程中的return和exit语句有什么区别?

c

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

如果在64位代码中使用32位int 0x80 Linux ABI会发生什么?

int 0x80在Linux上总是调用32位ABI,不管是什么模式,这就是所谓的:在args ebx,ecx...和系统调用号的/usr/include/asm/unistd_32.h.(或者在没有编译的64位内核上崩溃CONFIG_IA32_EMULATION).

64位代码应该使用syscall,从呼叫号码/usr/include/asm/unistd_64.h,并在args rdi,rsi等见什么调用约定UNIX和Linux系统上的i386和x86-64调用.如果您的问题被打上这样一个重复的,看你怎么说链接,细节应当使32位或64位代码的系统调用. 如果你想了解到底发生了什么,请继续阅读.


sys_write系统调用比syscall系统调用快,所以使用本机64位,int 0x80除非你正在编写多格式机器代码,当执行32或64位时运行相同的机器代码.(syscall始终以32位模式返回,因此它在64位用户空间中没有用,尽管它是有效的x86-64指令.)

相关:Linux系统的权威指南(在x86上)调用如何进行sysenterint 0x8032位系统调用,或sysenter64位系统调用,或调用vDSO进行"虚拟"系统调用syscall.加上有关系统调用的背景知识.


使用gettimeofday可以编写将以32位或64位模式组合的内容,因此它可以int 0x80在微基准测试结束时使用.

标准化函数和系统调用约定的官方i386和x86-64 System V psABI文档的当前PDF文件链接自https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI.

有关初学者指南,x86手册,官方文档和性能优化指南/资源,请参阅标记wiki.


但是,由于人们不断发布与使用代码的问题exit_group()在64位代码,或不小心建立64位二进制文件从源代码对于32位写的,我不知道是什么确切不会对当前的Linux怎样呢?

是否int 0x80保存/恢复所有的64位寄存器?它会将任何寄存器截断为32位吗?如果传递上半部分非零的指针args会发生什么?

如果你传递32位指针它是否有效?

linux assembly x86-64 system-calls abi

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

Can't call C standard library function on 64-bit Linux from assembly (yasm) code

I have a function foo written in assembly and compiled with yasm and GCC on Linux (Ubuntu) 64-bit. It simply prints a message to stdout using puts(), here is how it looks:

bits 64

extern puts
global foo

section .data

message:
  db 'foo() called', 0

section .text

foo:
  push rbp
  mov rbp, rsp
  lea rdi, [rel message]
  call puts
  pop rbp
  ret
Run Code Online (Sandbox Code Playgroud)

It is called by a C program compiled with GCC:

extern void foo();

int main() {
    foo(); …
Run Code Online (Sandbox Code Playgroud)

c linux assembly x86-64 yasm

7
推荐指数
2
解决办法
276
查看次数

Syscall实现exit()

我写了一个简单的C程序,只调用exit()函数,但是strace说二进制文件实际上是调用exit_group,exit()是一个exit_group()包装器吗?这两个功能是否相同?如果是这样,为什么编译器会选择exit_group()而不是exit()?

c x86 assembly gcc system-calls

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

如果汇编程序中没有退出系统调用会发生什么?

在汇编程序中,.text加载时0x08048000.在.data.bss部分来之后.

如果我没有exit在该.text部分中添加系统调用会发生什么?难道导致.data.bss被解释为代码造成"不可预测"的结果吗?程序何时终止 - 可能在执行每条"指令"之后?

我可以很容易地编写一个程序没有exit系统调用,但如果测试的.data,并.bss会得到执行的是我仍然不知道,因为我想我会知道那是在最罩产生的嘲笑,真正的机器代码.

我认为这个问题更多的是关于CPU和操作系统如何处理这种情况而不是汇编语言.

linux assembly operating-system termination

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

在装配中使用 printf 会导致管道输出为空,但在终端上有效

我尝试printf从我的汇编代码中使用,这是一个应该打印hello到标准输出的最小示例:

.section  .rodata
hello:
    .ascii  "hello\n\0"
.section .text
    .globl _start        
_start:
    movq $hello, %rdi     # first parameter
    xorl %eax, %eax       # 0 - number of used vector registers
    call printf        
#exit   
    movq $60, %rax
    movq $0, %rdi
    syscall
Run Code Online (Sandbox Code Playgroud)

我用

gcc -nostdlib try_printf.s -o try_printf -lc
Run Code Online (Sandbox Code Playgroud)

当我运行它时,它似乎工作:字符串hello被打印出来,退出状态是0

XXX$ ./try_printf
hello
XXX$ echo $?
0
XXX$
Run Code Online (Sandbox Code Playgroud)

但是当我尝试捕获文本时,很明显,某些内容无法正常工作:

XXX$ output=$(./try_printf) 
XXX$ echo $output

XXX$ 
Run Code Online (Sandbox Code Playgroud)

该变量output应具有 value hello,但为空。

我的用法有printf什么问题?

linux assembly printf glibc x86-64

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

从无法对齐RSP的函数调用时,glibc scanf分段错误

编译以下代码时:

global main
extern printf, scanf

section .data
   msg: db "Enter a number: ",10,0
   format:db "%d",0

section .bss
   number resb 4

section .text
main:
   mov rdi, msg
   mov al, 0
   call printf

   mov rsi, number
   mov rdi, format
   mov al, 0
   call scanf

   mov rdi,format
   mov rsi,[number]
   inc rsi
   mov rax,0
   call printf 

   ret
Run Code Online (Sandbox Code Playgroud)

使用:

nasm -f elf64 example.asm -o example.o
gcc -no-pie -m64 example.o -o example
Run Code Online (Sandbox Code Playgroud)

然后运行

./example
Run Code Online (Sandbox Code Playgroud)

它运行,打印:输入数字: 但随后崩溃并打印: 分段错误(核心已转储)

因此,printf可以正常工作,而scanf则不能。我对scanf有什么错呢?

linux assembly x86-64 nasm calling-convention

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

Nasm分割错误

对不起,我是汇编代码的新手.我编码这个线条

section .text
     global _start
_start:
     nop
main:
     mov eax, 1
     mov ebx, 2
     xor eax, eax
     ret
Run Code Online (Sandbox Code Playgroud)

我用这些命令编译:

nasm -f elf main.asm
ld -melf_i386 -o main main.o
Run Code Online (Sandbox Code Playgroud)

当我运行代码时,Linux抛出了分段错误错误(我正在使用Linux Mint Nadia 64位).为什么会产生这个错误?

提前致谢

linux x86 assembly nasm

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