Skip to content

Instantly share code, notes, and snippets.

@Trinitek
Last active October 25, 2016 06:21
Show Gist options
  • Select an option

  • Save Trinitek/73ba401c4239e2bc2691580c75a400b9 to your computer and use it in GitHub Desktop.

Select an option

Save Trinitek/73ba401c4239e2bc2691580c75a400b9 to your computer and use it in GitHub Desktop.
#include <stdio.h>
/*
* Here, we define a structure that groups 2 chars together as an
* addressable unit.
*
* Due to the nature of the way x86 processors copy multi-byte values
* to and from memory (this trait is known as endianness), the high
* and low bytes are flipped here in this structure. The x86
* architecture is a "little-endian" architecture, which means that
* bytes are read from and written to memory backwards. As an example,
* a value of 0xABCD in the AX register, such that AH contains 0xAB
* and AL contains 0xCD, when written to memory, will be visible as
* 0xCD, 0xAB if you were to inspect the program with a debugger.
*/
typedef struct {
char low;
char high;
} grouped_char;
/*
* This function returns the high byte of a grouped char.
*
* It uses the SHR instruction instead of accessing AH.
*/
char getHigh(grouped_char chars) {
char result;
asm("shr $8, %%ax;" // bitshift AH into AL
"mov %%al, %%bl;" // BL <-- AL
: "=b" (result) // resulting char is found in BL
: "a" (chars) // pass char group parameter into AX
);
return result;
}
/*
* This function returns the low byte of a grouped char.
*/
char getLow(grouped_char chars) {
char result;
asm("mov %%al, %%bl" // BL <-- AL, ignoring AH
: "=b" (result) // resulting char is found in BL
: "a" (chars) // pass char group parameter into AX
);
return result;
}
int main(void) {
grouped_char myChars;
myChars.high = 'A';
myChars.low = 'B';
printf("Group: %c %c\n", myChars.high, myChars.low);
printf("High: %c\n", getHigh(myChars));
printf("Low: %c\n", getLow(myChars));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment