这个问题来自于ffmpegg安装时编译器的报错:
E:\software\msys2\tmp\ccgdnG5s.s: Assembler messages:CC libavformat/alp.o
E:\software\msys2\tmp\ccgdnG5s.s:413: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:479: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:540: Error: operand CC libavformat/amr.o
type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:673: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:764: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:856: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:948: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:1039: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:1130: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:1262: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:1397: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:1647: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:1768: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:1963: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:2404: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:2619: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:2792: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:3158: Error: operand type mismatch for `shr'
E:\software\msys2\tmp\ccgdnG5s.s:3297: Error: operand type mismatch for `shr'
make: *** [ffbuild/common.mak:81: libavformat/adtsenc.o] Error 1
出自:
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef unsigned int __uint32_t;
typedef __int8_t int8_t;
typedef __uint8_t uint8_t;
typedef __uint32_t uint32_t;
typedef struct AVCodecParameters {
uint8_t *extradata;
int extradata_size;
} AVCodecParameters;
static inline uint32_t NEG_USR32(uint32_t a, int8_t s) {
__asm__("shrl %1, %0\n\t" : "+r"(a) : "ic"((uint8_t)(-s)));
return a;
}
即__asm__("shrl %1, %0\n\t" : "+r"(a) : "c"((-s)));这句的右移指令,mmpeg似乎想进行一个负数的偏移,(我不知道他怎么想的,啥情况会负数作偏移?),所以这个内联汇编一定要传入负数s,报错的原因在于gcc拒绝接收负数的立即数作为操作数,把"ic"改为"i",去掉立即数的约束即可成功编译了,参考https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108941
那么问题解决了,新的问题是,如果真的把负数传入,那么会发生什么事情?
我尝试对其经行了汇编,得到如下代码
#include
#include
#define SDL_MAIN_HANDLED
static inline uint32_t NEG_USR32(uint32_t a, int8_t s) {
__asm__("shrl %1, %0\n\t" : "+r"(a) : "c"((-s)));
return a;
}
int main()
{
printf("%d",NEG_USR32(3,1) );
}
对应汇编
.file "test.c"
.text
.def NEG_USR32; .scl 3; .type 32; .endef
.seh_proc NEG_USR32
NEG_USR32:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
.seh_endprologue
movl %ecx, 16(%rbp)
movl %edx, %eax
movb %al, 24(%rbp)
movzbl 24(%rbp), %eax
negl %eax
movl %eax, %edx
movl 16(%rbp), %eax
movl %edx, %ecx
/APP
# 5 "test.c" 1
shrl %cl, %eax
# 0 "" 2
/NO_APP
movl %eax, 16(%rbp)
movl 16(%rbp), %eax
popq %rbp
ret
.seh_endproc
.def __main; .scl 2; .type 32; .endef
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
movl $1, %edx
movl $3, %ecx
call NEG_USR32
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (GNU) 13.2.0"
用gdb打断点查看变量cl,得到如下输出
Thread 1 "test" hit Temporary breakpoint 5, main () at test.s:35
35 pushq %rbp
1: $eax = 0
(gdb) c
Continuing.
Thread 1 "test" hit Breakpoint 4, NEG_USR32 () at test.s:15
15 negl %eax
1: $eax = 1
(gdb) i r eax
eax 0x1 1
(gdb) n
16 movl %eax, %edx
1: $eax = -1
(gdb) i r eax
eax 0xffffffff -1
(gdb) n
[New Thread 27796.0x27d0]
17 movl 16(%rbp), %eax
1: $eax = -1
(gdb)
18 movl %edx, %ecx
1: $eax = 3
(gdb)
21 shrl %cl, %eax
1: $eax = 3
(gdb) i r eax
eax 0x3 3
(gdb) n
25 movl %eax, 16(%rbp)
1: $eax = 0
(gdb) i r cl
cl 0xff -1
cl就是-1值,eax即3,向右偏移-1位,就是偏移0xFF, 变成了0,看来硬件不会作正负判断。应该是向右移动了很大的数。