이 값은 0
- 0x7fff
및 0xffff8000
- 0xffffffff
에서 값을로드하는 데 유용하지만 다른 값은로드 할 수 없습니다.
즉시 비트 연산 opcode (ori
등)는 16 비트 직접 필드를 부호없는 값으로 해석합니다. 그러나 "은 0
문자 그대로를 의미합니다"동작이 addi
이 아닙니다.
당신은 레지스터에 0xfc10
의 상수를로드하는 두 개의 명령어를 사용해야합니다 : (당신이 임의의 32 비트 상수의 위쪽 절반을로드하는 것처럼, 또는 lis
) li
를 사용하여 0 레지스터를로드 한 후 또는 부호가없는 16 비트 값인 ori
.
$ cat test.c
unsigned int test(void)
{
return 0xfc10;
}
$ gcc -O2 -c test.c
$ objdump -d test.o
test.o: file format elf32-powerpc
Disassembly of section .text:
00000000 <test>:
0: 38 60 00 00 li r3,0
4: 60 63 fc 10 ori r3,r3,64528
8: 4e 80 00 20 blr
c: 60 00 00 00 nop
$
내가 이는 GNU 어셈블러가 하나에서 같은 값을로드하기 위해 자동으로 두 개의 명령어를 생성 어떤 방법이 있다고 생각하지 않습니다
이
는 gcc
이 상황에서 무엇을하는지 정확히 PowerPC 용으로 어셈블 할 때 소스 명령. 당신은 상수, 예를 들어,의 (서명) 높고 낮은 16 비트 반쪽을 추출하기 위해 @h
및 @l
접미사를 사용할 수 있습니다 그러나 : lis r3, [email protected] /* => li r3, 0x1234 */
ori r3, r3, [email protected] /* => ori r3, r3, 0x5678 */
당신은 임의의 상수로드에 대한 자신의 매크로를 작성하려면이 옵션을 사용할 수 있습니다 .. .
$ cat test2.s
.macro load_const rD, const
.if (\const >= -0x8000) && (\const <= 0x7fff)
li \rD, \const
.else
lis \rD, \[email protected]
ori \rD, \rD, \[email protected]
.endif
.endm
load_const r3, 0
load_const r4, 1
load_const r5, -1
load_const r6, 0x7fff
load_const r7, 0x8000
load_const r8, -32767
load_const r9, -32768
load_const r10, -32769
load_const r11, 0xfc10
$ as -mregnames -o test2.o test2.s
$ objdump -d test2.o
test2.o: file format elf32-powerpc
Disassembly of section .text:
00000000 <.text>:
0: 38 60 00 00 li r3,0
4: 38 80 00 01 li r4,1
8: 38 a0 ff ff li r5,-1
c: 38 c0 7f ff li r6,32767
10: 3c e0 00 00 lis r7,0
14: 60 e7 80 00 ori r7,r7,32768
18: 39 00 80 01 li r8,-32767
1c: 39 20 80 00 li r9,-32768
20: 3d 40 ff ff lis r10,-1
24: 61 4a 7f ff ori r10,r10,32767
28: 3d 60 00 00 lis r11,0
2c: 61 6b fc 10 ori r11,r11,64528
$
-1008 0xFC10과 같은 2의 보수 표현을가집니다.어쩌면 당신은 (0xfc10-0x10000)을 쓸 수 있습니까? –
또는 수동으로 0xFFFFFC10으로 부호 확장 하시겠습니까? –
@tc - 흥미 롭습니다. li 명령어는 16 비트 값만 허용하지만 li r3,0xFFFFFC10은 올바른 명령어입니다. – KeithSmith