尝试使用内联__asm()
在C中创建最小的32位代码。
到目前为止,我已经成功地将__asm()
代码大小变为23
字节。
我很好奇是否有方法通过使用
- 编译程序物理学
- 专用汇编指令
- vanilla C代码
示例
#include <stdio.h>
unsigned int CodeSize;
void print_binary(unsigned int number) { if (number >> 1) print_binary(number >> 1); putc((number & 1) ? '1' : '0', stdout); }
void reverseBits(unsigned int OriginalValue)
{
unsigned int ReversedValue = 0;
start_asm:
__asm__ (
"movl %1, %%eax\n" // load the value
"xorl %%ebx, %%ebx\n" // clear EBX (optimized)
"bsrl %%eax, %%ecx\n" // find highest order bit set to 1 in EAX
"incl %%ecx\n" // increment to get the correct number of iterations
"reverse:\n\t" // local label
"shrl $1, %%eax\n" // shift the LSB of EAX to the carry flag CF
"rcll $1, %%ebx\n" // the MSB of EBX goes into CF and CF's previous value goes into the LSB of EBX
"loop reverse\n" // loop back to the local label
"movl %%ebx, %0" // move the result to the output
: "=r" (ReversedValue) // output
: "r" (OriginalValue) // input
: "eax", "ebx", "ecx" // clobbered registers
);
end_asm:
CodeSize = (char *)&&end_asm - (char *)&&start_asm;
printf("\nOriginal: 0x%X ", OriginalValue); print_binary(OriginalValue);
printf("\nReversed: 0x%X ", ReversedValue); print_binary(ReversedValue);
printf("\n");
}
int main()
{
reverseBits(0xfeedface);
reverseBits(0xfeed);
reverseBits(0xfe);
printf("\nCodeSize: %u bytes\n", CodeSize);
return 0;
}
输出
Original: 0xFEEDFACE 11111110111011011111101011001110
Reversed: 0x735FB77F 1110011010111111011011101111111
Original: 0xFEEDFA 111111101110110111111010
Reversed: 0x5FB77F 10111111011011101111111
Original: 0xFEED 1111111011101101
Reversed: 0xB77F 1011011101111111
Original: 0xFE 11111110
Reversed: 0x7F 1111111
CodeSize: 23 bytes
更新
根据下面的有用注解,代码大小现在为13 bytes
uint32_t reverseBits(uint32_t OriginalValue) {
uint32_t ReversedValue = 0;
__asm__ (
"start_asm:\n" // start label
"xorl %%ebx, %%ebx\n" // clear EBX
"bsrl %1, %%ecx\n" // find highest order bit set to 1 in EAX (which is %1)
"reverse:\n" // local label for looping
"shrl $1, %1\n" // shift the LSB of EAX (which is %1) to the carry flag CF
"rcll $1, %%ebx\n" // the MSB of EBX goes into CF and CF's previous value goes into the LSB of EBX
"decl %%ecx\n" // manually decrement ECX
"jns reverse\n" // jump to reverse if sign flag is set (i.e., if ecx is negative)
"end_asm:\n" // end label
: "=b" (ReversedValue) // output directly to EBX
: "a" (OriginalValue) // input directly to EAX
: "ecx" // clobbered register
);
return ReversedValue;
}
2条答案
按热度按时间gajydyqb1#
10 bytes:
8yoxcaq72#
6 bytes