Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将数学表达式转换为x86程序集无符号与无符号_C++_Assembly_Unsigned_Signed - Fatal编程技术网

C++ 将数学表达式转换为x86程序集无符号与无符号

C++ 将数学表达式转换为x86程序集无符号与无符号,c++,assembly,unsigned,signed,C++,Assembly,Unsigned,Signed,我正在编写一个表达式计算器,它生成x86 64位程序集。我选择模仿C++编译器规则的变量类型(char to int促销等,和文字值)。然而,我有一个令人困惑的问题。当计算复杂的数学表达式时,我首先使用后缀转换。接下来,在内部跟踪数据类型的同时,逻辑根据转换和/或输入操作数类型跟踪数据类型。我的问题是当符号数变成未签名,反之亦然,由C++编译器< /强>中间表示?在汇编的生产过程中,我注意到ClangAssembly有时会使用movl,因为您可能会认为基于以前的数据类型,指令将是对扩展(movs

我正在编写一个表达式计算器,它生成x86 64位程序集。我选择模仿C++编译器规则的变量类型(char to int促销等,和文字值)。然而,我有一个令人困惑的问题。当计算复杂的数学表达式时,我首先使用后缀转换。接下来,在内部跟踪数据类型的同时,逻辑根据转换和/或输入操作数类型跟踪数据类型。我的问题是<强>当符号数变成未签名,反之亦然,由C++编译器< /强>中间表示?在汇编的生产过程中,我注意到ClangAssembly有时会使用movl,因为您可能会认为基于以前的数据类型,指令将是对扩展(movswl)进行签名。一般来说,我希望模仿C++编译器的类型转换以及中间处理的传统。

作为一个例子,考虑到我的程序(数据类型模拟C++)的输入:

在C++中,相同的代码产生为:>/P>
include <stdio.h>

int main(void) { 
short s_A=658;
long long ll_B=293;
unsigned int ui_C=94;

printf("%hi\n",s_A);
printf("%lld\n",ll_B);
printf("%u\n",ui_C);
printf("-------------------------\n");

ll_B=((394)-ui_C*(649)+(917)+ll_B-(80));
printf("%lld\n",ll_B);


printf("-------------------------\n");
printf("%hi\n",s_A);
printf("%lld\n",ll_B);
printf("%u\n",ui_C);

}
.text
    .file   "/home/anthony/comptest/simple/whole_short_int_longlong_simple/whole_short_int_longlong_simple_33.cpp"
    .globl  main
    .align  16, 0x90
    .type   main,@function
main:                                   # @main
    .cfi_startproc
# BB#0:
    pushq   %rbp
.Ltmp0:
    .cfi_def_cfa_offset 16
.Ltmp1:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
.Ltmp2:
    .cfi_def_cfa_register %rbp
    subq    $64, %rsp
    movabsq $.L.str, %rdi
    movw    $658, -2(%rbp)          # imm = 0x292
    movq    $293, -16(%rbp)         # imm = 0x125
    movl    $94, -20(%rbp)
    movswl  -2(%rbp), %esi
    movb    $0, %al
    callq   printf
    movabsq $.L.str1, %rdi
    movq    -16(%rbp), %rsi
    movl    %eax, -24(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str2, %rdi
    movl    -20(%rbp), %esi
    movl    %eax, -28(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str3, %rdi
    movl    %eax, -32(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str1, %rdi
    movl    $394, %esi              # imm = 0x18A
    imull   $649, -20(%rbp), %ecx   # imm = 0x289
    subl    %ecx, %esi
    addl    $917, %esi              # imm = 0x395
    movl    %esi, %ecx
    movl    %ecx, %edx
    addq    -16(%rbp), %rdx
    subq    $80, %rdx
    movq    %rdx, -16(%rbp)
    movq    -16(%rbp), %rsi
    movl    %eax, -36(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str3, %rdi
    movl    %eax, -40(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str, %rdi
    movswl  -2(%rbp), %esi
    movl    %eax, -44(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str1, %rdi
    movq    -16(%rbp), %rsi
    movl    %eax, -48(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str2, %rdi
    movl    -20(%rbp), %esi
    movl    %eax, -52(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    xorl    %ecx, %ecx
    movl    %eax, -56(%rbp)         # 4-byte Spill
    movl    %ecx, %eax
    addq    $64, %rsp
    popq    %rbp
    retq
.Ltmp3:
    .size   main, .Ltmp3-main
    .cfi_endproc

    .type   .L.str,@object          # @.str
    .section    .rodata.str1.1,"aMS",@progbits,1
.L.str:
    .asciz  "%hi\n"
    .size   .L.str, 5

    .type   .L.str1,@object         # @.str1
.L.str1:
    .asciz  "%lld\n"
    .size   .L.str1, 6

    .type   .L.str2,@object         # @.str2
.L.str2:
    .asciz  "%u\n"
    .size   .L.str2, 4

    .type   .L.str3,@object         # @.str3
.L.str3:
    .asciz  "-------------------------\n"
    .size   .L.str3, 27


    .ident  "Ubuntu clang version 3.6.2-1 (tags/RELEASE_362/final) (based on LLVM 3.6.2)"
    .section    ".note.GNU-stack","",@progbits
而gcc生产

    .file   "whole_short_int_longlong_simple_33.cpp"
    .section    .rodata
.LC0:
    .string "%hi\n"
.LC1:
    .string "%lld\n"
.LC2:
    .string "%u\n"
.LC3:
    .string "-------------------------"
    .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    $16, %rsp
    movw    $658, -14(%rbp)
    movq    $293, -8(%rbp)
    movl    $94, -12(%rbp)
    movswl  -14(%rbp), %eax
    movl    %eax, %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movq    -8(%rbp), %rax
    movq    %rax, %rsi
    movl    $.LC1, %edi
    movl    $0, %eax
    call    printf
    movl    -12(%rbp), %eax
    movl    %eax, %esi
    movl    $.LC2, %edi
    movl    $0, %eax
    call    printf
    movl    $.LC3, %edi
    call    puts
    movl    -12(%rbp), %eax
    imull   $649, %eax, %eax
    movl    $1311, %edx
    subl    %eax, %edx
    movl    %edx, %eax
    movl    %eax, %edx
    movq    -8(%rbp), %rax
    addq    %rdx, %rax
    subq    $80, %rax
    movq    %rax, -8(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rsi
    movl    $.LC1, %edi
    movl    $0, %eax
    call    printf
    movl    $.LC3, %edi
    call    puts
    movswl  -14(%rbp), %eax
    movl    %eax, %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movq    -8(%rbp), %rax
    movq    %rax, %rsi
    movl    $.LC1, %edi
    movl    $0, %eax
    call    printf
    movl    -12(%rbp), %eax
    movl    %eax, %esi
    movl    $.LC2, %edi
    movl    $0, %eax
    call    printf
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010"
    .section    .note.GNU-stack,"",@progbits
和叮当声产生:

include <stdio.h>

int main(void) { 
short s_A=658;
long long ll_B=293;
unsigned int ui_C=94;

printf("%hi\n",s_A);
printf("%lld\n",ll_B);
printf("%u\n",ui_C);
printf("-------------------------\n");

ll_B=((394)-ui_C*(649)+(917)+ll_B-(80));
printf("%lld\n",ll_B);


printf("-------------------------\n");
printf("%hi\n",s_A);
printf("%lld\n",ll_B);
printf("%u\n",ui_C);

}
.text
    .file   "/home/anthony/comptest/simple/whole_short_int_longlong_simple/whole_short_int_longlong_simple_33.cpp"
    .globl  main
    .align  16, 0x90
    .type   main,@function
main:                                   # @main
    .cfi_startproc
# BB#0:
    pushq   %rbp
.Ltmp0:
    .cfi_def_cfa_offset 16
.Ltmp1:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
.Ltmp2:
    .cfi_def_cfa_register %rbp
    subq    $64, %rsp
    movabsq $.L.str, %rdi
    movw    $658, -2(%rbp)          # imm = 0x292
    movq    $293, -16(%rbp)         # imm = 0x125
    movl    $94, -20(%rbp)
    movswl  -2(%rbp), %esi
    movb    $0, %al
    callq   printf
    movabsq $.L.str1, %rdi
    movq    -16(%rbp), %rsi
    movl    %eax, -24(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str2, %rdi
    movl    -20(%rbp), %esi
    movl    %eax, -28(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str3, %rdi
    movl    %eax, -32(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str1, %rdi
    movl    $394, %esi              # imm = 0x18A
    imull   $649, -20(%rbp), %ecx   # imm = 0x289
    subl    %ecx, %esi
    addl    $917, %esi              # imm = 0x395
    movl    %esi, %ecx
    movl    %ecx, %edx
    addq    -16(%rbp), %rdx
    subq    $80, %rdx
    movq    %rdx, -16(%rbp)
    movq    -16(%rbp), %rsi
    movl    %eax, -36(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str3, %rdi
    movl    %eax, -40(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str, %rdi
    movswl  -2(%rbp), %esi
    movl    %eax, -44(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str1, %rdi
    movq    -16(%rbp), %rsi
    movl    %eax, -48(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    movabsq $.L.str2, %rdi
    movl    -20(%rbp), %esi
    movl    %eax, -52(%rbp)         # 4-byte Spill
    movb    $0, %al
    callq   printf
    xorl    %ecx, %ecx
    movl    %eax, -56(%rbp)         # 4-byte Spill
    movl    %ecx, %eax
    addq    $64, %rsp
    popq    %rbp
    retq
.Ltmp3:
    .size   main, .Ltmp3-main
    .cfi_endproc

    .type   .L.str,@object          # @.str
    .section    .rodata.str1.1,"aMS",@progbits,1
.L.str:
    .asciz  "%hi\n"
    .size   .L.str, 5

    .type   .L.str1,@object         # @.str1
.L.str1:
    .asciz  "%lld\n"
    .size   .L.str1, 6

    .type   .L.str2,@object         # @.str2
.L.str2:
    .asciz  "%u\n"
    .size   .L.str2, 4

    .type   .L.str3,@object         # @.str3
.L.str3:
    .asciz  "-------------------------\n"
    .size   .L.str3, 27


    .ident  "Ubuntu clang version 3.6.2-1 (tags/RELEASE_362/final) (based on LLVM 3.6.2)"
    .section    ".note.GNU-stack","",@progbits
请注意,问题在rbx寄存器的评估范围内(EBX=32)。因为最后一个操作数是文本,所以我的逻辑在内部将这些值记为有符号int32位。因此,当加宽到64位时,会发出movslq,以符号扩展该值。而gcc(c编译器规则)则通过将32位数据移动到另一个寄存器(0填充上半部分)进行零扩展,然后将其作为64位数字引用


我还想解决另外两个稍微复杂一点的问题(进位、溢出(整数、SSE和FPU)、无符号/有符号等),因此,如果您擅长x86 64上的汇编,我是一个行为良好的对话者。对互联网的研究确实产生了一些与这一主题相关的结果。然而,我还没有找到一个明确的包含这两种恭维理解的文本。

第4.5节解释了如何将一个值转换为它自己的类型:

4.5整体促销[conv.prom]

  • 除bool、char16\u t、char32\u t或wchar\u t以外的整数类型的PR值,其整数转换秩(4.13)小于 如果int可以表示所有值,则int可以转换为int类型的prvalue 源类型的值;否则,源pr值可以是 已转换为类型为unsigned int的prvalue

  • char16\u t、char32\u t或wchar\u t(3.9.1)类型的PR值可转换为以下第一种类型的PR值: 表示其基础类型的所有值:int、unsigned int、, 长整型、无符号长整型、长整型或无符号长整型。 如果该列表中的任何类型都不能表示其 基础类型,类型为char16\u t、char32\u t或wchar\u t的PR值可以 将转换为其基础类型的prvalue

  • 基础类型不固定(7.2)的非范围枚举类型的prvalue可以转换为 以下类型可以表示枚举的所有值 (即7.2中所述的最小值至最大值范围内的值): 整型、无符号整型、长整型、无符号长整型、长整型或 无符号长整型。如果该列表中的任何类型都不能 表示枚举的所有值,一个未作用域的值 枚举类型可以转换为扩展整数的prvalue 最小整数转换秩(4.13)大于秩的类型 long的,其中枚举的所有值都可以 代表。如果有两个这样的扩展类型,那么有符号的类型是 选择

  • 基础类型为固定(7.2)的非范围枚举类型的prvalue可以转换为其基础类型的prvalue。 此外,如果可以对其基础类型应用积分提升, 非作用域枚举类型的右值,其基础类型为 fixed还可以转换为提升的基础的prvalue 类型

  • 如果int可以表示整型位字段(9.6)的所有值,则整型位字段(9.6)的prvalue可以转换为int类型的prvalue 位域;否则,如果为unsigned,则可以将其转换为unsigned int int可以表示位字段的所有值。如果位字段为 更大,但没有整体的推广适用于它。如果位字段 一个枚举类型,它被视为该类型的任何其他值 推广目的

  • bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为一
  • 这些转换称为整体促销

C++标准的第5节解释表达式中的提升。 。。。还有很多其他的事情

  • 否则,应在两个平台上执行整体促销(4.5) 操作数。[59]则以下规则应适用于 提升的操作数:

    • 如果两个操作数的类型相同,则不需要进一步转换 需要

    • 否则,如果两个操作数都具有有符号整数类型或都具有 无符号整数类型,类型为较小整数的操作数 转换秩应转换为具有 更高的等级

    • 否则,如果具有无符号整数类型的操作数具有秩 大于或等于其他操作数类型的秩, 带符号整数类型的操作数应转换为 无符号整数类型的操作数

    • 否则,如果带符号整数类型的操作数的类型 用无符号表示操作数类型的所有值 整数类型,具有无符号整数类型的操作数
      ll_B=((394)-ui_C*(649)+(917)+ll_B-(80));
      
      ll_B=394-ui_C*649+917+ll_B-80;