gpt4 book ai didi

assembly - 四元运算符和长运算符有什么区别

转载 作者:行者123 更新时间:2023-12-03 06:32:21 25 4
gpt4 key购买 nike

简单地说,我有以下代码:

#include <stdio.h>
#define MAXNO 100
void selectionSort(int [], int);
int main() // main.c
{
int no = 0, i ;
int data[MAXNO] ;
printf("Enter the data, terminate with Ctrl+D\n") ;
while(scanf("%d", &data[no]) != EOF) ++no;
selectionSort(data, no) ;
printf("Data in sorted Order are: ") ;
for(i = 0; i < no; ++i) printf("%d ", data[i]);
putchar('\n') ;
return 0 ;
}

当我运行时,我生成了以下汇编代码cc -S -Wall main.c

    .file   "main.c"
.section .rodata
.align 8
.LC0:
.string "Enter the data, terminate with Ctrl+D"
.LC1:
.string "%d"
.LC2:
.string "Data in sorted Order are: "
.LC3:
.string "%d "
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $416, %rsp
movl $0, -408(%rbp)
movl $.LC0, %edi
call puts
jmp .L2
.L3:
addl $1, -408(%rbp)
.L2:
leaq -400(%rbp), %rax
movl -408(%rbp), %edx
movslq %edx, %rdx
salq $2, %rdx
addq %rdx, %rax
movq %rax, %rsi
movl $.LC1, %edi
movl $0, %eax
call __isoc99_scanf
cmpl $-1, %eax
jne .L3
movl -408(%rbp), %edx
leaq -400(%rbp), %rax
movl %edx, %esi
movq %rax, %rdi
call selectionSort
movl $.LC2, %edi
movl $0, %eax
call printf
movl $0, -404(%rbp)
jmp .L4
.L5:
movl -404(%rbp), %eax
cltq
movl -400(%rbp,%rax,4), %eax
movl %eax, %esi
movl $.LC3, %edi
movl $0, %eax
call printf
addl $1, -404(%rbp)
.L4:
movl -404(%rbp), %eax
cmpl -408(%rbp), %eax
jl .L5
movl $10, %edi
call putchar
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",@progbits

我没有得到的是:

四元运算和长运算(例如 movqmovl)之间有什么区别。我知道一个用于 64 位操作,另一个用于 32 位操作,但这里整数被视为 32 位,对吗?那么为什么代码中混合了 movq 和 movl(或任何其他操作)呢?

编辑:

忘记添加我的系统的详细信息:

Linux Z510 3.13.0-58-generic #97-Ubuntu SMP Wed Jul 8 02:56:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

最佳答案

从 C 角度来看,“Long”或“Integer”值的大小取决于编译器,而不是体系结构。可以保证 long C 类型至少与 unsigned int 一样长,但除此之外什么也没有。这就是为什么位长度特定类型被添加到 C 标准中,允许您根据需要定义大小。您的编译器似乎选择使用 32 位整数,就像 64 位 ISA 上的大多数 C 实现一样。

除此之外,还有对堆栈上值的引用。您正在处理的系统上的堆栈宽度似乎是 64 位,这是有道理的,因为它允许您推送单个寄存器的内容并保持 64 位对齐。 (但这仅与保存/恢复调用保留的寄存器相关:堆栈上的局部变量可以打包在一个 8 字节堆栈“槽”内。每个函数 arg 都放在一个单独的槽中,但所有这些函数都少于 6 个args,因此 x86-64 System V 调用约定将它们全部传递到寄存器中。)

<小时/>

在 x86 中,一个“字”是 16 位(在将 16 位 8086 扩展到 386 或 AMD64 时,他们没有重命名现有术语)。

在英特尔术语中,双字是 32 位,四字是 64 位。 (就像 cdqe 将双字符号扩展为 qword)。

AT&T 操作数大小后缀为 l(表示双字)和 q(表示 qword)。 l 可能代表“long”,可以追溯到 386 年初或更早的时候,当时设计语法,并且与 C 中 long 的宽度无关。

例如,movl $0, -408(%rbp) 可能是 int no = 0 初始值设定项,存储 4 字节 0。在许多情况下,后缀是多余的,其大小由寄存器操作数隐含,例如 movl $.LC1, %edi 将地址放入寄存器中(在 Linux 非 PIE 可执行文件中,因此保证符号绝对地址适合以 32 位立即数表示。)EDI 是 RDI 的低 32 位。将其隐式零扩展写入 RDI。

关于assembly - 四元运算符和长运算符有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31635129/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com