我在C中有以下方法,它采用两个16位短整数:
返回结果:
short __declspec(naked) getchecksum(short s1, short s2)
{
__asm
{
mov ax, word ptr [esp+4]
mov bx, word ptr [esp+8]
add ax, bx
jnc skip_add
add ax, 1
skip_add:
not ax
ret
}
}
我必须在内联汇编中编写它,因为我不知道如何在不使用汇编程序的情况下测试进位标志。有谁知道这样做的方法?
答案 0 :(得分:5)
不(C根本没有标志的概念),但这并不意味着你不能得到相同的结果。如果使用32位整数进行加法,则第17位是进位。所以你可以这样写:
uint16_t getchecksum(uint16_t s1, uint16_t s2)
{
uint32_t u1 = s1, u2 = s2;
uint32_t sum = u1 + u2;
sum += sum >> 16;
return ~sum;
}
我已将这些类型设为无符号以防止出现问题。在您的平台上可能没有必要。
答案 1 :(得分:3)
您无需访问标志即可进行更高精度的算术运算。如果总和小于任何一个操作数,则有一个进位,所以你可以这样做
short __declspec(naked) getchecksum(short s1, short s2)
{
short s = s1 + s2;
if ((unsigned short)s < (unsigned short)s1)
s++;
return ~s;
}
关于添加和执行SO已经有很多问题:Efficient 128-bit addition using carry flag,Multiword addition in C
但是在C操作中,总是至少在int类型中完成,因此如果int在系统中的位数超过16位,则可以简单地添加它。在你的情况下,内联汇编是16位x86所以我猜你在Turbo C上应该尽快摆脱(原因:Why not to use Turbo C++?)。在具有16位int的其他系统中,您可以使用long,标准
保证至少为32位short __declspec(naked) getchecksum(short s1, short s2)
{
long s = s1 + s2;
return ~((s & 0xffff) + ((s >> 16) & 0x1));
}