GCC 错误地将函数内联到 asm 块
GCC incorrectly inlining function with asm block
在将代码从 Watcom 移植到 GCC 的过程中,我注意到生成的函数不正确,并且无法弄清楚为什么会这样。这是最小的例子:
#include <stdio.h>
bool InstallExceptionHandler(int exceptionNo, void (*handler)())
{
bool result;
asm volatile (
"mov ax, 0x203 \n"
"mov cx, cs \n"
"int 0x31 \n"
"sbb eax, eax \n"
"not eax \n"
: "=eax" (result)
: "ebx" (exceptionNo), "edx" (handler)
: "cc", "cx"
);
return result;
}
void Exception13Handler(){}
main()
{
if (!InstallExceptionHandler(13, Exception13Handler)) {
printf("Success!");
return 0;
} else {
printf("Failure.");
return 1;
}
}
在第 63 行,函数 InstallExceptionHandler() 被内联,但它剩下的只是 asm 块。缺少设置输入寄存器 edx 和 ebx 的代码。如果给定函数 __attribute__((noinline)) 并发出实际调用,则会生成正确的代码。这是编译器中的错误还是我的代码无效?
48 .globl _main
50 _main:
51 LFB15:
52 .cfi_startproc
53 0000 55 push ebp
54 .cfi_def_cfa_offset 8
55 .cfi_offset 5, -8
56 0001 89E5 mov ebp, esp
57 .cfi_def_cfa_register 5
58 0003 83E4F0 and esp, -16
59 0006 83EC10 sub esp, 16
60 0009 E8000000 call ___main
60 00
61 /APP
62 # 15 "b.cpp" 1
63 000e 66B80302 mov ax, 0x203
64 0012 668CC9 mov cx, cs
65 0015 CD31 int 0x31
66 0017 19C0 sbb eax, eax
67 0019 F7D0 not eax
命令行:gcc -O3 -m32 -masm=intel -Wa,-adhlns=b.lst b.cpp,
gcc -v 输出:
使用内置规格。
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=f:/mingw/bin/../libexec/gcc/mingw32/4.8.1/lto-wrapper.exe
目标:mingw32
配置为:../gcc-4.8.1/configure --prefix=/mingw --host=mingw32 --build=mingw32 --without-pic
--enable-shared --enable-static --with-gnu-ld --enable-lto --enable-libssp --disable-multilib --ena
ble-languages=c,c++,fortran,objc,obj-c++,ada --disable-sjlj-exceptions --with-dwarf2 --disable-win32
-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --with-gmp=/usr/src/pkg/gm
p-5.1.2-1-mingw32-src/bld --with-mpc=/usr/src/pkg/mpc-1.0.1-1-mingw32-src/bld --with-mpfr= --with-sy
stem-zlib --with-gnu-as --enable-decimal-float=yes --enable-libgomp --enable-threads --with-libiconv
-prefix=/mingw32 --with-libintl-prefix=/mingw --disable-bootstrap LDFLAGS=-s CFLAGS=-D_USE_32BIT_TIM
E_T
线程模型:win32
gcc 版本 4.8.1 (GCC)
约束不是寄存器名称,通过指定约束“ebx”,您允许编译器使用带符号的 32 位常量、RBX/EBX/BX/BL 寄存器或任何 SSE 寄存器。 GCC 已选择使用常量,并将用常量替换任何出现的 %1
。
要使用您希望的寄存器,您需要约束 a
、b
和 d
。
在将代码从 Watcom 移植到 GCC 的过程中,我注意到生成的函数不正确,并且无法弄清楚为什么会这样。这是最小的例子:
#include <stdio.h>
bool InstallExceptionHandler(int exceptionNo, void (*handler)())
{
bool result;
asm volatile (
"mov ax, 0x203 \n"
"mov cx, cs \n"
"int 0x31 \n"
"sbb eax, eax \n"
"not eax \n"
: "=eax" (result)
: "ebx" (exceptionNo), "edx" (handler)
: "cc", "cx"
);
return result;
}
void Exception13Handler(){}
main()
{
if (!InstallExceptionHandler(13, Exception13Handler)) {
printf("Success!");
return 0;
} else {
printf("Failure.");
return 1;
}
}
在第 63 行,函数 InstallExceptionHandler() 被内联,但它剩下的只是 asm 块。缺少设置输入寄存器 edx 和 ebx 的代码。如果给定函数 __attribute__((noinline)) 并发出实际调用,则会生成正确的代码。这是编译器中的错误还是我的代码无效?
48 .globl _main
50 _main:
51 LFB15:
52 .cfi_startproc
53 0000 55 push ebp
54 .cfi_def_cfa_offset 8
55 .cfi_offset 5, -8
56 0001 89E5 mov ebp, esp
57 .cfi_def_cfa_register 5
58 0003 83E4F0 and esp, -16
59 0006 83EC10 sub esp, 16
60 0009 E8000000 call ___main
60 00
61 /APP
62 # 15 "b.cpp" 1
63 000e 66B80302 mov ax, 0x203
64 0012 668CC9 mov cx, cs
65 0015 CD31 int 0x31
66 0017 19C0 sbb eax, eax
67 0019 F7D0 not eax
命令行:gcc -O3 -m32 -masm=intel -Wa,-adhlns=b.lst b.cpp, gcc -v 输出: 使用内置规格。 COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=f:/mingw/bin/../libexec/gcc/mingw32/4.8.1/lto-wrapper.exe 目标:mingw32 配置为:../gcc-4.8.1/configure --prefix=/mingw --host=mingw32 --build=mingw32 --without-pic --enable-shared --enable-static --with-gnu-ld --enable-lto --enable-libssp --disable-multilib --ena ble-languages=c,c++,fortran,objc,obj-c++,ada --disable-sjlj-exceptions --with-dwarf2 --disable-win32 -registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --with-gmp=/usr/src/pkg/gm p-5.1.2-1-mingw32-src/bld --with-mpc=/usr/src/pkg/mpc-1.0.1-1-mingw32-src/bld --with-mpfr= --with-sy stem-zlib --with-gnu-as --enable-decimal-float=yes --enable-libgomp --enable-threads --with-libiconv -prefix=/mingw32 --with-libintl-prefix=/mingw --disable-bootstrap LDFLAGS=-s CFLAGS=-D_USE_32BIT_TIM E_T 线程模型:win32 gcc 版本 4.8.1 (GCC)
约束不是寄存器名称,通过指定约束“ebx”,您允许编译器使用带符号的 32 位常量、RBX/EBX/BX/BL 寄存器或任何 SSE 寄存器。 GCC 已选择使用常量,并将用常量替换任何出现的 %1
。
要使用您希望的寄存器,您需要约束 a
、b
和 d
。