当前位置: 首页 > 知识库问答 >
问题:

为什么char和短数据存储在4字节寄存器中?[重复]

萧升
2023-03-14

我正在学习将C转换为汇编,然后我发现数据存储在4字节寄存器中。

注意:我使用-Og-g编译C,使用gdbdisas main!另外,我的电脑是64位的。

下面是关于char的代码,对应于assembly(我认为short和char是同一个问题,所以我放两个代码中的一个):

#include <stdio.h>

int main(void) {
    const int LEN = 3;
    char c[LEN];
    c[0] = 1;
    c[1] = 2;
    c[2] = 3;

    for(int i = 0; i < LEN; i ++) {
        printf("%d\n", c[i]);
    }

    return 0;
}

反汇编代码的一部分!

   0x000000000000116e <+5>:     sub    $0x10,%rsp
   0x0000000000001172 <+9>:     mov    %fs:0x28,%rax
   0x000000000000117b <+18>:    mov    %rax,0x8(%rsp)
   0x0000000000001180 <+23>:    xor    %eax,%eax
   0x0000000000001182 <+25>:    movb   $0x1,0x5(%rsp)
   0x0000000000001187 <+30>:    movb   $0x2,0x6(%rsp)
   0x000000000000118c <+35>:    movb   $0x3,0x7(%rsp)
   0x0000000000001191 <+40>:    mov    $0x0,%ebx
   0x0000000000001196 <+45>:    jmp    0x11b9 <main+80>
   0x0000000000001198 <+47>:    movslq %ebx,%rax

   # why %edx?
   0x000000000000119b <+50>:    movsbl 0x5(%rsp,%rax,1),%edx


   0x00000000000011a0 <+55>:    lea    0xe5d(%rip),%rsi        # 0x2004
   0x00000000000011a7 <+62>:    mov    $0x1,%edi
   0x00000000000011ac <+67>:    mov    $0x0,%eax
   0x00000000000011b1 <+72>:    callq  0x1070 <__printf_chk@plt>
   0x00000000000011b6 <+77>:    add    $0x1,%ebx
   0x00000000000011b9 <+80>:    cmp    $0x2,%ebx
   0x00000000000011bc <+83>:    jle    0x1198 <main+47>

我学习了一些关于java数据类型的知识,隐马尔可夫模型,比如字节,字符,或者短代码被提升为int。我不确定他们有什么关系。

共有2个答案

解明辉
2023-03-14

当您仅在表达式中引用char或short变量时,语言规则表示它立即提升为int。

即使您将一个变量转换为char,它仍然会立即升级为int,因此如果您说(char)c,这与说(int)(char)(int)c是一样的。

对于较短的数据类型,这种自动且立即升级到int的操作独立于函数调用和参数传递。

但是为什么char和short需要提升呢?

这是由语言定义的。

来自ISO/IEC 9899:201x委员会草案-2011年4月12日N1570

示例2执行片段c1、c2
/**/
c1=c1 c2<“整数提升”要求抽象机器将每个变量的值提升为int大小,然后将两个int相加并截断总和。如果两个字符的添加可以在没有§5.1.2.3环境15溢出的情况下完成,或者通过无提示的溢出包装来产生正确的结果,那么实际执行只需要产生相同的结果,可能忽略提升。

夏嘉德
2023-03-14

对于%d格式,您指定要打印“int”,因此需要将值加载到(至少)int大小的寄存器。

 类似资料:
  • 为什么数据段寄存器(ds/es/fs/gs)在GDB中总是显示为0x0?例如,无论我看哪个进程或线程,“info reg”似乎总是给我这样的输出: 我正在尝试调试glibc代码,在我正在分解的函数中看到fs段前缀: 我知道这就是glibc将如何引用线程的TCB(tcbhead_t)来获取TLS和其他重要内容。所以这不是意味着每个线程都需要一个唯一的描述符条目吗?每个线程不应该对fs寄存器有一个唯一

  • 我的数字类型是有符号二的补码整数。 在内存寄存器%rdi/edi/di中,我有0xFFFFFFFF。在%rsi/esi/si中,我有0x8000000。 如何正确添加这些? 我认为答案是: 由于我添加的是完整的32位寄存器,因此可以添加完整的0xFFFFFFFF和0x8000000。 我把一个有符号整数加到一个有符号整数上,它们都是32位的。我实际上是在加-2147483648和0x8000000

  • 根据Intel在x64中的说法,以下寄存器被称为通用寄存器(RAX、RBX、RCX、RDX、RBP、RSI、RDI、RSP和R8-R15)https://software.Intel.com/en-us/articles/indroduction-to-x64-assembly。 在下面的文章中,RBP和RSP是特殊用途寄存器(RBP指向当前堆栈帧的底部,RSP指向当前堆栈帧的顶部)。https:

  • 我需要只使用%RAX、%RBX、%RCX、%RDX、%RSI和%RDI(还有%RSP和%RBP)编写像素化汇编代码 GCC编写的程序集代码: 已将%dl更改为%rdx:

  • 本文向大家介绍char 型变量中能不能存储一个中文汉字,为什么?相关面试题,主要包含被问及char 型变量中能不能存储一个中文汉字,为什么?时的应答技巧和注意事项,需要的朋友参考一下 char 类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char 类型占2个字节(16 比特),所以放一个中文是没问

  • 问题内容: 任何人都可以用C,C ++和Java清楚地解释一下。什么都在堆栈上,什么都在堆上以及何时分配。 我所知道的, 每个函数调用的所有局部变量(无论是基元,指针还是引用变量)都在新的堆栈框架上。 使用new或malloc创建的所有内容都会进入堆。 我对几件事感到困惑。 是在堆上创建的对象成员的引用/基元是否也存储在堆上? 以及在每个框架中递归创建的方法的那些本地成员呢?它们都在堆栈上吗?如果