How can I do these operations in C?
I am converting the assembly code to C so that I can use it with the current compiler environment that I have to work with.
I have achieved 2 operations. I don't know how to translate to C. Does anyone know how to do this?
In both cases, it offset
is an unsigned 32-bit integer, and shift
is a signed integer value. C_FLAG is bool.
OP1:
__asm {
__asm mov ecx, shift
__asm ror offset, cl
}
FP2:
__asm {
__asm bt dword ptr C_FLAG, 0
__asm rcr offset, 1
}
Thanks a lot for your experience.
PS: I am not an original developer and I have not seen much x86 assembly code ...
a source to share
Assuming flags are not used to store persistent state (which is a reasonable assumption), OP1 is equivalent to:
/* Precondition: `*offset` is in range 0..0xFFFFFFFF */
void inline op1(unsigned long *offset, int shift)
{
shift = ((unsigned)shift) % 32;
if (shift)
*offset = ((*offset >> shift) | (*offset << (32 - shift))) & 0xFFFFFFFFUL;
}
and OP2 is equivalent:
/* Precondition: `*offset` is in range 0..0xFFFFFFFF */
void inline op2(unsigned long *offset, unsigned long C_FLAG)
{
*offset = (*offset >> 1) | ((C_FLAG & 1) << 31);
}
(On 32-bit systems, the long
condition is automatically met).
a source to share
rotate right discussion: http://www.osix.net/modules/article/?id=320
illustrated descriptions: http://www.penguin.cz/~literakl/intel/r.html
Hope it helps
a source to share
For bit shifting as per your first example, use the operator <<
. In the C language, there are no shift movements, which are often referred to as rotating shifts. You will need to perform the operation yourself:
unsigned char carry;
carry = byte & 0x80; // Save the Most Significant bit for 8-bit byte.
byte <<= 1; // Left shift by one, insert a 0 as the least significant bit.
byte |= carry; // Put the rotated bit back into the byte.
Some processors also have a rotate through carry operation that will rotate the carry value on the next shift. This assumes it carry
is a global variable.
To test bits in C, you will use the &
(binary AND operator) and possibly the ~
(negate) operator . To test the most significant bit in an 8-bit byte:
if (byte & 0x80)
{
// bit is a 1
}
else
{
// bit is a 0
}
With all that said, you will need to figure out why the carry flag ( C_FLAG
) is being used and design another system around it. Typically, the carry bit is invalid outside of the assembly language function in which it is used. Certain tightly coupled assembly language functions may violate this rule. In this case, rewrite the assembly language rather than debug it. Redesign the entire program!
a source to share
for the second op
__asm bt dword ptr C_FLAG, 0
sets the bit carry flag in C_FLAG (so 1 or 0)
__asm rcr offset, 1
Left rotation that rotates 33 bits using the carry flag as the 33rd bit. (and the results put the 33rd bit in the carry flag. Which (I think) is the same as
offset = offset << 1 + C_FLAG ? 1:0
(unless you need the carry flag later)
EDIT - for some reason I was reading rcr as rcl. So what is more like
offset = offset >> 1 | (C_FLAG ? 1<<31 : 0)
a source to share
Although more or less covered, I would do it this way:
OP 1: Rotates the right operation over offset
, shift
places. In C, it could be something like this:
offset = (offset >> shift) | (offset << (WORD_LENGTH - shift);
You can get the length of a word with sizeof(void *) * 8
eg.
OP 2: I think this op implements the RRX operation in x86 assembly. This is another type of right rotation operation where the carry flag is used to move the 33-bit amount. In C, it could be something like this:
offset = (C_FLAG << 31) | (offset >> 1);
Where C_FLAG
is the carry flag, you should learn more about what exactly this value is bool
actually used in the code you have.
a source to share