Language
C
Compiler
gcc 13.2.0
Options
Warnings
C99
no pedantic
#include <stdio.h>
/* aの下位8bit + bの下位8bit + c を計算する */
/* [OF][CF][和8bit] を返す */
int adc_asm(int a, int b, int c) {
int sum, flags;
__asm__ __volatile__ (
"test %4, %4\n\t" /* CF = 0 にする */
"jz 1f\n\t"
"stc\n" /* c != 0 ならば、CF = 1 にする */
"1:\n\t"
"adc %%dl, %%al\n\t"
"mov %%eax, %1\n\t"
"pushf\n\t"
"mov (%%rsp), %0\n\t"
"add $8, %%rsp\n\t"
: "=r"(flags), "=r"(sum) : "a"(a), "d"(b), "r"(c));
return (sum & 0xff) | (flags & 0x0800 ? 0x200 : 0) | (flags & 1 ? 0x100 : 0);
}
int adc(int a, int b, int c) {
int sum = (a & 0xff) + (b & 0xff) + c;
int overflow = (a & 0x80) == (b & 0x80) && (a & 0x80) != (sum & 0x80);
return (sum & 0x1ff) | (overflow ? 0x200 : 0);
}
/* aの下位8bit - (bの下位8bit + c) を計算する */
/* [OF][CF][差8bit] を返す */
int sbb_asm(int a, int b, int c) {
int diff, flags;
__asm__ __volatile__ (
"test %4, %4\n\t" /* CF = 0 にする */
"jz 1f\n\t"
"stc\n" /* c != 0 ならば、CF = 1 にする */
"1:\n\t"
"sbb %%dl, %%al\n\t"
"mov %%eax, %1\n\t"
"pushf\n\t"
"mov (%%rsp), %0\n\t"
"add $8, %%rsp\n\t"
: "=r"(flags), "=r"(diff) : "a"(a), "d"(b), "r"(c));
return (diff & 0xff) | (flags & 0x0800 ? 0x200 : 0) | (flags & 1 ? 0x100 : 0);
}
int sbb(int a, int b, int c) {
int diff = (a & 0xff) + (~b & 0xff) + !c;
int overflow = (a & 0x80) != (b & 0x80) && (a & 0x80) != (diff & 0x80);
return ((diff ^ 0x100) & 0x1ff) | (overflow ? 0x200 : 0);
}
int main(void) {
int a, b, c;
for (a = 0; a <= 0xff; a++) {
for (b = 0; b <= 0xff; b++) {
for (c = 0; c <= 1; c++) {
int r1 = adc_asm(a, b, c);
int r2 = adc(a, b, c);
int r3 = sbb_asm(a, b, c);
int r4 = sbb(a, b, c);
if (r1 != r2) {
printf("adc error (a, b, c) = (0x%02x, 0x%02x, %d) expected = 0x%03x, actual = 0x%03x\n", a, b, c, r1, r2);
}
if (r3 != r4) {
printf("sbb error (a, b, c) = (0x%02x, 0x%02x, %d) expected = 0x%03x, actual = 0x%03x\n", a, b, c, r3, r4);
}
}
}
}
return 0;
}
$ gcc prog.c -Wall -Wextra -std=c99
Exit Code:
0