能否向右位移?且偏移大小是-1?

这个问题来自于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,看来硬件不会作正负判断。应该是向右移动了很大的数。

你可能感兴趣的:(linux,ffmpeg)