gnu 汇编程序中的寄存器 %fs:<num> 是什么?

问题描述

这个简单的c代码

文件bar.c

#include <stdio.h>

#define BSIZE 5

typedef struct
{
    int count;
    int ar[BSIZE];
} foo;

int main()
{
    foo f = {.count = 0};
     printf("%ld\n",sizeof(foo));
}

输出 24 作为结构体的大小 (5*4 + 4),所以它是正确的。气体代码如下:

    .text
    .section    .rodata
.LC0:
    .string "%ld\n"
    .text
    .globl  main
    .type   main,@function
main:
    endbr64 
    pushq   %rbp    #
    movq    %rsp,%rbp  #,subq    $32,%rsp   #,# bar.c:12: {
    movq    %fs:40,%rax    # MEM[(<address-space-1> long unsigned int *)40B],tmp85
    movq    %rax,-8(%rbp)  # tmp85,D.2347
    xorl    %eax,%eax  # tmp85
# bar.c:13:     foo f = {.count = 0};
    movq    $0,-32(%rbp)   #,f
    movq    $0,-24(%rbp)   #,-16(%rbp)   #,f
# bar.c:14:      printf("%ld\n",sizeof(foo));
    movl    $24,%esi   #,leaq    .LC0(%rip),%rdi    #,movl    $0,%eax    #,call    printf@plt  #
    movl    $0,_5
# bar.c:15: }
    movq    -8(%rbp),%rdx  # D.2347,tmp86
    subq    %fs:40,%rdx    # MEM[(<address-space-1> long unsigned int *)40B],tmp86
    je  .L3 #,call    __stack_chk_fail@plt    #
.L3:
    leave   
    ret 
    .size   main,.-main
    .ident  "GCC: (Ubuntu 10.2.0-13ubuntu1) 10.2.0"
    .section    .note.GNU-stack,"",@progbits
    .section    .note.gnu.property,"a"
    .align 8
    .long    1f - 0f
    .long    4f - 1f
    .long    5
0:
    .string  "GNU"
1:
    .align 8
    .long    0xc0000002
    .long    3f - 2f
2:
    .long    0x3
3:
    .align 8
4:
 

现在我对此输出有多个问题:

  1. 为什么struct的大小为subq $32,%rsp时会出现24?为什么不只从堆栈中减去 24,而是需要另一个 8 bytes 来做什么?对齐?

  2. 什么是 movq %fs:40,%rax # MEM[(<address-space-1> long unsigned int *)40B],tmp85 ?什么是寄存器 %fs40 是什么意思,偏移量?编译器生成的注释暗示了什么?没有数据类型 long unsigned int * ???

此声明:

# bar.c:13:     foo f = {.count = 0};
   movq  $0,-32(%rbp)  #,f
   movq  $0,-24(%rbp)  #,-16(%rbp)  #,f

我不完全明白。从我的结构定义来看,我猜

 -32(%rbp) == count
 -24(%rbp) == ar[0]
 -20(%rbp) == ar[1]
 -16(%rbp) == ar[2]
 -12(%rbp) == ar[3]
 -8(%rbp) == ar[4]

这是 struct foo 在堆栈中的正确对齐吗?否则如何对齐?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)