x86 32 비트 머신 코드, 24 21 바이트
changelog : -3 바이트 : @peter ferrie의 표준 add / cmp / jbe / add를 DAS 핵으로 교체
64 비트 : 여전히 24 바이트 Long 모드는 DAS opcode를 제거했습니다.
16 비트 모드 : 기본 피연산자 크기는 16 비트이지만 문제 사양은 기본적으로 32 비트입니다. 하드 코드 된 8 진수를 포함합니다.
bswap표준 순서로 수동 int-> hex로 바이트 리버스 (가장 중요한 니블 우선, 16 진수를 char 출력 버퍼에 오름차순으로 기록) 바이트 바이트에서 니블 사이의 순서를 전환하기 위해 루프를 풀 필요가 없습니다. 바이트 간.
void lehex(char buf[8] /*edi*/, uint32_t x /*esi*/);64 비트 모드에서 작동하지 않는 것을 제외하고 x86-64 System V처럼 호출 가능 합니다. (에 대한 EDI의 출력 포인터가 필요합니다 stosb. 입력 번호는 ECX 또는 EAX 이외의 레지스터에있을 수 있습니다.)
1 lehex:
2 00000000 0FCE bswap esi
3 00000002 6A08 push 8 ; 8 hex digits
4 00000004 59 pop ecx
5 .loop: ;do{
6 00000005 C1C604 rol esi, 4 ; rotate high nibble to the bottom
7
8 00000008 89F0 mov eax, esi
9 0000000A 240F and al, 0x0f ; isolate low nibble
10 0000000C 3C0A cmp al, 10 ; set CF according to digit <= 9
11 0000000E 1C69 sbb al, 0x69 ; read CF, set CF and conditionally set AF
12 00000010 2F das ; magic, which happens to work
13
14 00000011 AA stosb ; *edi++ = al
15 00000012 E2F1 loop .loop ; }while(--ecx)
16
17 00000014 C3 ret
크기 = 0x15 = 21 바이트
TIO FASM 32 비트 x86 테스트 케이스 ( asm 호출자 포함)는 write시스템 호출을 사용 하여 출력을 두 번 호출 한 후 버퍼에 2 개의 문자열을 추가 한 후 출력을 작성합니다. 숫자와 문자 사이의 경계에서 9와 A를 포함하여 모든 16 진수 0..F를 테스트합니다.
DAS해킹 - 86 낮은 니블의 수행을 위해, 반 캐리 플래그가 있습니다. 2 개의 2 자리 BCD 정수를 뺀 후 사용하기 위해 DAS 명령어와 같은 압축 BCD 항목에 유용합니다. AL의 낮은 니블이 0-9 범위를 벗어나면 여기에서 확실히 남용됩니다.
주목 if (old_AL > 99H) or (old_CF = 1)AL ← AL − 60H;매뉴얼의 조작 섹션 THEN 부분을 확인하십시오. sbb는 항상 CF를 설정하므로 부분이 항상 발생합니다. 대문자의 ASCII 범위는 선택의 동기를 부여합니다.sub al, 0x69
cmp 0xD, 0xA CF를 설정하지 않습니다
- sbb 는 DAS에 대한 입력
0xD - 0x69으로 AL = 0xA4으로 랩핑됩니다 . (그리고 CF를 설정하고 AF를 지 웁니다)
- DAS의 첫 번째 부분에 AL-= 6 없음 (4> 9가 false이고 AF = 0이므로)
- 두 번째 부분에서 AL-= 0x60
0x44 , 아스키 코드'D'
숫자 대 :
cmp 0x3, 0xA CF를 설정
- sbb
3 - 0x69 - 1 = AL = 0x99이며 CF 및 AF를 설정합니다
- DAS의 첫 번째 부분에 AL-= 6 없음 (9> 9는 거짓이지만 AF는 설정 됨), 0x93
- 두 번째 부분의 AL-= 0x60이며의 ASCII 코드 인 0x33이 남습니다
'3'.
0x6aSBB에서 빼면 모든 숫자 <= 9에 대해 AF가 설정되어 모든 숫자가 동일한 논리를 따릅니다. 그리고 모든 알파벳 16 진수에 대해 지우십시오. 즉, DAS의 9 / A 분할 처리를 올바르게 활용합니다.
일반적으로 (성능을 위해) 스칼라 루프 또는 분기가없는 2x lea및 cmp/cmov조건부 추가에 대한 조회 테이블을 사용 합니다. 그러나 2 바이트 al, imm8명령어는 코드 크기에서 큰 승리입니다.
- 64 버전 버전 : 사이에, 다른 그냥 부분 and al, 0xf과 stosb.
;; x86-64 int -> hex in 8 bytes
10 0000000C 0430 add al, '0'
11 0000000E 3C39 cmp al, '9'
12 00000010 7602 jbe .digit
13 00000012 0427 add al, 'a'-10 - '0' ; al = al>9 ? al+'a'-10 : al+'0'
14 .digit:
공지 사항은 그 add al, '0' 항상 실행하고 조건 추가는의 차이를 추가 'a'-10하고 '0'단지를 만들기 위해, if대신에 if/ else.
테스트와 같은 사용하여 작동 main으로 발신자를 내 C 응답 , 사용 char buf[8]및 printf("%.8s\n", buf).