This is not meant to be an in-depth tutorial on x86 Assembly but it is simply a follow up of the article on programming Windows 32 using MASM32. The mentioned article can be found here.()
I can already see a lot of people wondering why they should just want to learn x86 Assembly let alone go ahead and learn it. See today programming get along their business of writing software quite happily without lay down a iota of Assembly code and still end up being quite productive. There really must be some reason as to why you’d want to learn Assembly.
Without going into too much I think its fare to know that Assembly is the defacto language when you want to do some really cool stuff as close as possible to the computer hardware as you can get.
For instance if you want to access some features directly on the processors such as Intel’s and AMD’s processors then the only way is through Assembly. Okay maybe you want to reverse Engineer a program. Again, there you go. Assembly is the way forward. Other low level tasks like Boot Loaders are also coded in Assembly. It is also used in a more negative way to crack Software, or patching software and software updates etc.
The if Assembly can do such neat things and more then why do most software developers shun developing applications using Assembly? Some would say that it’s probably too difficult to start with. I do not agree. I’d say rather than being difficult Assembly is pretty different. Anyway. As far as I am concerned there is basically one downfall to developing in Assembly. It is just too time consuming and I would not recommend doing entire projects using Assembly.
My best bet is to develop in a language like C or C++ and just code the specific functions or rather algorithms that you’d want to squeeze our every ounce of speed in Assembly. It is also good to know that there are compilers that can take an entire program coded in a high level language and compiled into assembly which can be further optimized by hand. However! As far as compilers go I think they do a pretty good job in optimizing the code in the first place so doing it by hand may not pull in any significant advantage.
Okay, now that we’ve got that cleared out of the way I can begin to talk about x86 Assembly. X86 Assembly is the flavor, so to speak of Assembly language that adheres to an instruction set architecture of a class of processors popularly used today for all modern computers. As of 2009, x86 primarily refers to IA-32 and/or x86-64 seeing we no longer have processors that are primarily 16 bit as far as computers are concerned.
The original x86 Microprocessor came way back in 1978. That was the 8086. The naming convention change in 1993 to Pentium which is used to this day with other variations coming in 1998 popularly know as Celeron and in 2006 Core, Core 2, Core duo. Also on this list is the Xeon normally used on Servers. All these are Intel microprocessors.
The AMD range of microprocessors include Athlon, Turion, Durion, Sempron and Opteron. The Opteron is a rival to Xeon and Sempron can be equated to Celeron.
To start off x86 Assembly Architectures possesse 8 General-Purpose Registers (GPR), 6 Segment Registers, 1 Flags Register and a single Instruction Pointer.
General Purpose Registers
EAX/AX/AL/AH – Accumulator registers. Used for arithmetic operations.
ECX/CX/CL/CH – Counter registers. Used for shift,rotate instructions and loops.
EDX/DX/DL/DH – Data registers. Used in arithmetic operations and I/O operations.
EBX/BX/BL/BH – Base registers. Used as a pointer to data.
ESP/SP – Stack Pointer registers. Pointer to the top of the stack.
EBP/BP – Stack Base Pointer registers. Used to point to the base of the stack.
ESI/SI – Source registers. Used as a pointer to a source in stream operations.
EDI/DI – Destination registers. Used as a pointer to a destination in stream operations.
The fist four can be accessed in these four ways:
As 32-bit: EAX, ECX, EDX and EBX
As 16-bit: AX, CX, DX and BX
the LSB of a 16-bit register: AL, CL, DL and BL
the MSB of a 16-bit register: AH, CH, DH and BH.
While the last four can be accessed in these two ways:
As 32-bit: ESP, EBP, ESI and EDI
As 16-bit: SP, BP, SI and DI.
Segment Registers
SS – Stack Segment. Pointer to the stack.
CS – Code Segment. Pointer to the code.
DS – Data Segment. Pointer to the data.
ES – Extra Segment. Pointer to extra data. As in ‘E’ = “Extra”.
FS – F Segment. Pointer to more extra data. (‘F’ comes after ‘E’).
GS – G Segment. Pointer to much more extra data. (‘G’ comes after ‘F’).
EFLAGS Register
This is used to store and control the results of operations and the state of the processor.
The Flags are named as follows taking not that the first item of every bullet represents the bit number. In this case it would be 0-31 because remember we are dealing with 32bit FLAGS. The ones left out are named as 0 or not used:
0: CF: Carry Flag – Set if the last arithmetic operation carried (addition) or borrowed (subtracted) a bit beyond the size of the register. This is then checked when the operation is followed with an add-with-carry or subtract-with-borrow to deal with values that are too large for one register to hold.
2: PF: Parity Flag – Set if the number of set bits in the least significant byte is a multiple of 2.
4: AF: Adjust Flag. Carry of Binary Code Decimal (BCD) numbers arithmetic operations.
6: ZF: Zero Flag. Set if the result of an operation is Zero (0).
7: SF: Sign Flag. Set if the result of an operation is negative.
8: TF: Trap Flag. Set if step by step debugging.
9: IF: Interruption Flag. Set if interrupts are enabled.
10: DF: Direction Flag. Stream direction. If set, string operations will decrement their pointer rather than incrementing it, reading memory backwards.
11: OF: Overflow Flag. Set if signed arithmetic operations result in a value too large for the register to contain.
12-13: IOPL: I/O Privilege Level field (2 bits) flag. I/O Privilege Level of the current process.
14: NT: Nested Task flag. Controls chaining of interrupts it is usually set if the current process is linked to the next process.
16: RF: Resume Flag. Response to debug exceptions.
17: VM: Virtual-8086 Mode. Set if in 8086 compatibility mode.
18: AC: Alignment Check. Set if alignment checking in of memory references are done.
19: VIF: Virtual Interrupt Flag. Virtual image of IF.
20: VIP: Virtual Interrupt Pending flag. Set if an interrupt is pending.
21: ID: Identification Flag. Support for CPUID instruction if can be set.
Instruction Pointer
EIP: This register contains the address of the next instruction to be executed if no branching is done. It should be read from the stack.
As far as memory is concerned its good to remember that x86 Architectures memory is little Endian mean memory is written kind of inverted. for example take this 32 bit hexadecimal value 0xA2B3FF2B. It would be written in memory as 2BFFB3A2. This would look somewhat like this when doing a memory dump. 0×2B 0xFF 0xB3 0xA2. The 0x here denotes a Hexadecimal number.
Another thing to note about numbers is there happens to be an equivalent negative for every positive integer. For instance, the integer 1 has a corresponding -1. To represent that you simply invert the digits representation of the digit in binary and add one. Like in the example here:
0001 : Actual Digit representing 1.
1110 : The representation figures have be inverted.
1111 : Here 1 has been added.
Therefore
0001 = 1
1111 = -1
To address a register you’d have to do this, take note that this is an actual syntax:
mov ax, bx ; move the contents of bx to ax
mov ax, 2; move the value of 2 into ax
mov ax, 0×0101; move 0×0101 into ax
Direct memory addressing:
mov ax, [102h] ; Actual address
Basically move instruction copies src to dest as shown below.
mov dest, src
The xchg instruction swaps the src operand with the dest operand.
xchg dest, src
Move zero extend; the movz instruction copies the src operand in the dest operand and pads the remaining bits not provided by src with zeros (0).
movzx dest, src
As you can see, this is the general syntax to follow while moving data and addressing registers.
Following the same convention in Arithmetic:
add dest, src
sub dest, src
for multiply you multiply arg b corresponding byte length in a register
mul arg
imul arg
division works like multiplication on it divides the byte length by arg
div arg
idiv arg
Logical instructions would be as:
or dest, src
xor dest, src
not arg
Control Flow instructions would be:
test arg2, arg1
cmp arg2, arg1
jmp loc
Well like I said earlier this wasn’t meant to be an in-depth tutorial as I’d probably need an entire book to get into this. This just shows the consistency in the instruction sets and once you master the representations of the labels and instruction keywords then you are well on your way to understanding how to use assembly language.
The instruction set used here is within the x86 Assembly coding conventions. It is my hope that this brief will start one off on their way to learning Assembly. Next I will show you how you can crack or patch an application using the skills you can learn in Assembly.
Read: How To Program Windows 32 Using The Microsoft AssemblerThis is not meant to be an in-depth tutorial on x86 Assembly but it is simply a follow up of the article on programming Windows 32 using MASM32. The mentioned article can be found here.()
I can already see a lot of people wondering why they should just want to learn x86 Assembly let alone go ahead and learn it. See today programming get along their business of writing software quite happily without lay down a iota of Assembly code and still end up being quite productive. There really must be some reason as to why you’d want to learn Assembly.
Without going into too much I think its fare to know that Assembly is the defacto language when you want to do some really cool stuff as close as possible to the computer hardware as you can get.
For instance if you want to access some features directly on the processors such as Intel’s and AMD’s processors then the only way is through Assembly. Okay maybe you want to reverse Engineer a program. Again, there you go. Assembly is the way forward. Other low level tasks like Boot Loaders are also coded in Assembly. It is also used in a more negative way to crack Software, or patching software and software updates etc.
The if Assembly can do such neat things and more then why do most software developers shun developing applications using Assembly? Some would say that it’s probably too difficult to start with. I do not agree. I’d say rather than being difficult Assembly is pretty different. Anyway. As far as I am concerned there is basically one downfall to developing in Assembly. It is just too time consuming and I would not recommend doing entire projects using Assembly.
My best bet is to develop in a language like C or C++ and just code the specific functions or rather algorithms that you’d want to squeeze our every ounce of speed in Assembly. It is also good to know that there are compilers that can take an entire program coded in a high level language and compiled into assembly which can be further optimized by hand. However! As far as compilers go I think they do a pretty good job in optimizing the code in the first place so doing it by hand may not pull in any significant advantage.
Okay, now that we’ve got that cleared out of the way I can begin to talk about x86 Assembly. X86 Assembly is the flavor, so to speak of Assembly language that adheres to an instruction set architecture of a class of processors popularly used today for all modern computers. As of 2009, x86 primarily refers to IA-32 and/or x86-64 seeing we no longer have processors that are primarily 16 bit as far as computers are concerned.
The original x86 Microprocessor came way back in 1978. That was the 8086. The naming convention change in 1993 to Pentium which is used to this day with other variations coming in 1998 popularly know as Celeron and in 2006 Core, Core 2, Core duo. Also on this list is the Xeon normally used on Servers. All these are Intel microprocessors.
The AMD range of microprocessors include Athlon, Turion, Durion, Sempron and Opteron. The Opteron is a rival to Xeon and Sempron can be equated to Celeron.
To start off x86 Assembly Architectures possesse 8 General-Purpose Registers (GPR), 6 Segment Registers, 1 Flags Register and a single Instruction Pointer.
General Purpose Registers
EAX/AX/AL/AH – Accumulator registers. Used for arithmetic operations.
ECX/CX/CL/CH – Counter registers. Used for shift,rotate instructions and loops.
EDX/DX/DL/DH – Data registers. Used in arithmetic operations and I/O operations.
EBX/BX/BL/BH – Base registers. Used as a pointer to data.
ESP/SP – Stack Pointer registers. Pointer to the top of the stack.
EBP/BP – Stack Base Pointer registers. Used to point to the base of the stack.
ESI/SI – Source registers. Used as a pointer to a source in stream operations.
EDI/DI – Destination registers. Used as a pointer to a destination in stream operations.
The fist four can be accessed in these four ways:
As 32-bit: EAX, ECX, EDX and EBX
As 16-bit: AX, CX, DX and BX
the LSB of a 16-bit register: AL, CL, DL and BL
the MSB of a 16-bit register: AH, CH, DH and BH.
While the last four can be accessed in these two ways:
As 32-bit: ESP, EBP, ESI and EDI
As 16-bit: SP, BP, SI and DI.
Segment Registers
SS – Stack Segment. Pointer to the stack.
CS – Code Segment. Pointer to the code.
DS – Data Segment. Pointer to the data.
ES – Extra Segment. Pointer to extra data. As in ‘E’ = “Extra”.
FS – F Segment. Pointer to more extra data. (‘F’ comes after ‘E’).
GS – G Segment. Pointer to much more extra data. (‘G’ comes after ‘F’).
EFLAGS Register
This is used to store and control the results of operations and the state of the processor.
The Flags are named as follows taking not that the first item of every bullet represents the bit number. In this case it would be 0-31 because remember we are dealing with 32bit FLAGS. The ones left out are named as 0 or not used:
0: CF: Carry Flag – Set if the last arithmetic operation carried (addition) or borrowed (subtracted) a bit beyond the size of the register. This is then checked when the operation is followed with an add-with-carry or subtract-with-borrow to deal with values that are too large for one register to hold.
2: PF: Parity Flag – Set if the number of set bits in the least significant byte is a multiple of 2.
4: AF: Adjust Flag. Carry of Binary Code Decimal (BCD) numbers arithmetic operations.
6: ZF: Zero Flag. Set if the result of an operation is Zero (0).
7: SF: Sign Flag. Set if the result of an operation is negative.
8: TF: Trap Flag. Set if step by step debugging.
9: IF: Interruption Flag. Set if interrupts are enabled.
10: DF: Direction Flag. Stream direction. If set, string operations will decrement their pointer rather than incrementing it, reading memory backwards.
11: OF: Overflow Flag. Set if signed arithmetic operations result in a value too large for the register to contain.
12-13: IOPL: I/O Privilege Level field (2 bits) flag. I/O Privilege Level of the current process.
14: NT: Nested Task flag. Controls chaining of interrupts it is usually set if the current process is linked to the next process.
16: RF: Resume Flag. Response to debug exceptions.
17: VM: Virtual-8086 Mode. Set if in 8086 compatibility mode.
18: AC: Alignment Check. Set if alignment checking in of memory references are done.
19: VIF: Virtual Interrupt Flag. Virtual image of IF.
20: VIP: Virtual Interrupt Pending flag. Set if an interrupt is pending.
21: ID: Identification Flag. Support for CPUID instruction if can be set.
Instruction Pointer
EIP: This register contains the address of the next instruction to be executed if no branching is done. It should be read from the stack.
As far as memory is concerned its good to remember that x86 Architectures memory is little Endian mean memory is written kind of inverted. for example take this 32 bit hexadecimal value 0xA2B3FF2B. It would be written in memory as 2BFFB3A2. This would look somewhat like this when doing a memory dump. 0×2B 0xFF 0xB3 0xA2. The 0x here denotes a Hexadecimal number.
Another thing to note about numbers is there happens to be an equivalent negative for every positive integer. For instance, the integer 1 has a corresponding -1. To represent that you simply invert the digits representation of the digit in binary and add one. Like in the example here:
0001 : Actual Digit representing 1.
1110 : The representation figures have be inverted.
1111 : Here 1 has been added.
Therefore
0001 = 1
1111 = -1
To address a register you’d have to do this, take note that this is an actual syntax:
mov ax, bx ; move the contents of bx to ax
mov ax, 2; move the value of 2 into ax
mov ax, 0×0101; move 0×0101 into ax
Direct memory addressing:
mov ax, [102h] ; Actual address
Basically move instruction copies src to dest as shown below.
mov dest, src
The xchg instruction swaps the src operand with the dest operand.
xchg dest, src
Move zero extend; the movz instruction copies the src operand in the dest operand and pads the remaining bits not provided by src with zeros (0).
movzx dest, src
As you can see, this is the general syntax to follow while moving data and addressing registers.
Following the same convention in Arithmetic:
add dest, src
sub dest, src
for multiply you multiply arg b corresponding byte length in a register
mul arg
imul arg
division works like multiplication on it divides the byte length by arg
div arg
idiv arg
Logical instructions would be as:
or dest, src
xor dest, src
not arg
Control Flow instructions would be:
test arg2, arg1
cmp arg2, arg1
jmp loc
Well like I said earlier this wasn’t meant to be an in-depth tutorial as I’d probably need an entire book to get into this. This just shows the consistency in the instruction sets and once you master the representations of the labels and instruction keywords then you are well on your way to understanding how to use assembly language.
The instruction set used here is within the x86 Assembly coding conventions. It is my hope that this brief will start one off on their way to learning Assembly. Next I will show you how you can crack or patch an application using the skills you can learn in Assembly.
Read: How To Program Windows 32 Using The Microsoft Assembler
This is not meant to be an in-depth tutorial on x86 Assembly but it is simply a follow up of the article on programming Windows 32 using MASM32. The mentioned article can be found here.
I can already see a lot of people wondering why they should just want to learn x86 Assembly let alone go ahead and learn it. See today programming get along their business of writing software quite happily without lay down a iota of Assembly code and still end up being quite productive. There really must be some reason as to why you’d want to learn Assembly.
Without going into too much I think its fare to know that Assembly is the defacto language when you want to do some really cool stuff as close as possible to the computer hardware as you can get.
For instance if you want to access some features directly on the processors such as Intel’s and AMD’s processors then the only way is through Assembly. Okay maybe you want to reverse Engineer a program. Again, there you go. Assembly is the way forward. Other low level tasks like Boot Loaders are also coded in Assembly. It is also used in a more negative way to crack Software, or patching software and software updates etc.
The if Assembly can do such neat things and more then why do most software developers shun developing applications using Assembly? Some would say that it’s probably too difficult to start with. I do not agree. I’d say rather than being difficult Assembly is pretty different. Anyway. As far as I am concerned there is basically one downfall to developing in Assembly. It is just too time consuming and I would not recommend doing entire projects using Assembly.
My best bet is to develop in a language like C or C++ and just code the specific functions or rather algorithms that you’d want to squeeze our every ounce of speed in Assembly. It is also good to know that there are compilers that can take an entire program coded in a high level language and compiled into assembly which can be further optimized by hand. However! As far as compilers go I think they do a pretty good job in optimizing the code in the first place so doing it by hand may not pull in any significant advantage.
Okay, now that we’ve got that cleared out of the way I can begin to talk about x86 Assembly. X86 Assembly is the flavor, so to speak of Assembly language that adheres to an instruction set architecture of a class of processors popularly used today for all modern computers. As of 2009, x86 primarily refers to IA-32 and/or x86-64 seeing we no longer have processors that are primarily 16 bit as far as computers are concerned.
The original x86 Microprocessor came way back in 1978. That was the 8086. The naming convention change in 1993 to Pentium which is used to this day with other variations coming in 1998 popularly know as Celeron and in 2006 Core, Core 2, Core duo. Also on this list is the Xeon normally used on Servers. All these are Intel microprocessors.
The AMD range of microprocessors include Athlon, Turion, Durion, Sempron and Opteron. The Opteron is a rival to Xeon and Sempron can be equated to Celeron.
To start off x86 Assembly Architectures possesse 8 General-Purpose Registers (GPR), 6 Segment Registers, 1 Flags Register and a single Instruction Pointer.
General Purpose Registers
- EAX/AX/AL/AH – Accumulator registers. Used for arithmetic operations.
- ECX/CX/CL/CH – Counter registers. Used for shift,rotate instructions and loops.
- EDX/DX/DL/DH – Data registers. Used in arithmetic operations and I/O operations.
- EBX/BX/BL/BH – Base registers. Used as a pointer to data.
- ESP/SP – Stack Pointer registers. Pointer to the top of the stack.
- EBP/BP – Stack Base Pointer registers. Used to point to the base of the stack.
- ESI/SI – Source registers. Used as a pointer to a source in stream operations.
- EDI/DI – Destination registers. Used as a pointer to a destination in stream operations.
The fist four can be accessed in these four ways:
- As 32-bit: EAX, ECX, EDX and EBX
- As 16-bit: AX, CX, DX and BX
- the LSB of a 16-bit register: AL, CL, DL and BL
- the MSB of a 16-bit register: AH, CH, DH and BH.
While the last four can be accessed in these two ways:
- As 32-bit: ESP, EBP, ESI and EDI
- As 16-bit: SP, BP, SI and DI.
Segment Registers
- SS – Stack Segment. Pointer to the stack.
- CS – Code Segment. Pointer to the code.
- DS – Data Segment. Pointer to the data.
- ES – Extra Segment. Pointer to extra data. As in ‘E’ = “Extra”.
- FS – F Segment. Pointer to more extra data. (‘F’ comes after ‘E’).
- GS – G Segment. Pointer to much more extra data. (‘G’ comes after ‘F’).
EFLAGS Register
This is used to store and control the results of operations and the state of the processor.
The Flags are named as follows taking not that the first item of every bullet represents the bit number. In this case it would be 0-31 because remember we are dealing with 32bit FLAGS. The ones left out are named as 0 or not used:
- 0: CF: Carry Flag – Set if the last arithmetic operation carried (addition) or borrowed (subtracted) a bit beyond the size of the register. This is then checked when the operation is followed with an add-with-carry or subtract-with-borrow to deal with values that are too large for one register to hold.
- 2: PF: Parity Flag – Set if the number of set bits in the least significant byte is a multiple of 2.
- 4: AF: Adjust Flag. Carry of Binary Code Decimal (BCD) numbers arithmetic operations.
- 6: ZF: Zero Flag. Set if the result of an operation is Zero (0).
- 7: SF: Sign Flag. Set if the result of an operation is negative.
- 8: TF: Trap Flag. Set if step by step debugging.
- 9: IF: Interruption Flag. Set if interrupts are enabled.
- 10: DF: Direction Flag. Stream direction. If set, string operations will decrement their pointer rather than incrementing it, reading memory backwards.
- 11: OF: Overflow Flag. Set if signed arithmetic operations result in a value too large for the register to contain.
- 12-13: IOPL: I/O Privilege Level field (2 bits) flag. I/O Privilege Level of the current process.
- 14: NT: Nested Task flag. Controls chaining of interrupts it is usually set if the current process is linked to the next process.
- 16: RF: Resume Flag. Response to debug exceptions.
- 17: VM: Virtual-8086 Mode. Set if in 8086 compatibility mode.
- 18: AC: Alignment Check. Set if alignment checking in of memory references are done.
- 19: VIF: Virtual Interrupt Flag. Virtual image of IF.
- 20: VIP: Virtual Interrupt Pending flag. Set if an interrupt is pending.
- 21: ID: Identification Flag. Support for CPUID instruction if can be set.
Instruction Pointer
EIP: This register contains the address of the next instruction to be executed if no branching is done. It should be read from the stack.
As far as memory is concerned its good to remember that x86 Architectures memory is little Endian mean memory is written kind of inverted. for example take this 32 bit hexadecimal value 0xA2B3FF2B. It would be written in memory as 2BFFB3A2. This would look somewhat like this when doing a memory dump. 0×2B 0xFF 0xB3 0xA2. The 0x here denotes a Hexadecimal number.
Another thing to note about numbers is there happens to be an equivalent negative for every positive integer. For instance, the integer 1 has a corresponding -1. To represent that you simply invert the digits representation of the digit in binary and add one. Like in the example here:
0001 : Actual Digit representing 1.
1110 : The representation figures have be inverted.
1111 : Here 1 has been added.
Therefore
0001 = 1
1111 = -1
To address a register you’d have to do this, take note that this is an actual syntax:
mov ax, bx ; move the contents of bx to ax
mov ax, 2; move the value of 2 into ax
mov ax, 0×0101; move 0×0101 into ax
Direct memory addressing:
mov ax, [102h] ; Actual address
Basically move instruction copies src to dest as shown below.
mov dest, src
The xchg instruction swaps the src operand with the dest operand.
xchg dest, src
Move zero extend; the movz instruction copies the src operand in the dest operand and pads the remaining bits not provided by src with zeros (0).
movzx dest, src
As you can see, this is the general syntax to follow while moving data and addressing registers.
Following the same convention in Arithmetic:
add dest, src
sub dest, src
for multiply you multiply arg b corresponding byte length in a register
mul arg
imul arg
division works like multiplication on it divides the byte length by arg
div arg
idiv arg
Logical instructions would be as:
or dest, src
xor dest, src
not arg
Control Flow instructions would be:
test arg2, arg1
cmp arg2, arg1
jmp loc
Well like I said earlier this wasn’t meant to be an in-depth tutorial as I’d probably need an entire book to get into this. This just shows the consistency in the instruction sets and once you master the representations of the labels and instruction keywords then you are well on your way to understanding how to use assembly language.
The instruction set used here is within the x86 Assembly coding conventions. It is my hope that this brief will start one off on their way to learning Assembly. Next I will show you how you can crack or patch an application using the skills you can learn in Assembly.
Read: How To Program Windows 32 Using The Microsoft Assembler
Related posts:
- How To Program Windows 32 Using The Microsoft Assembler
- Upgrading From Nokia PC Suite to Nokia Ovi Suite (The Conclusion)
I think this website is a great idea. I agree with you on most things.
[...] Read: A Brief Understanding of x86 Assembly Language [...]