Advertisement
2_2002-2004 Miscellaneous #127311

using inline assemby - learn about registers, instructions, and a basic instruction list

Heres a tutorial which will teach you the basics so you can do some simple inline assembly. Contains code examples and compliments the examples which can also be found on PSC. Also contains x86 instruction list.

AI

AI Summary: This codebase represents a historical implementation of the logic described in the metadata. Our preservation engine analyzes the structure to provide context for modern developers.

Source Code
original-source
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
<META NAME="Generator" CONTENT="Internet Assistant for Word Version 3.0">
</HEAD>
<BODY>
<FONT SIZE=2><P>inline assembly with Visual C++ tutorial</P>
<P>compliments the examples,</P>
<P>also contains simple instruction list</P>
<P> </P>
<P> </P>
First off let me explain that this was
a request from some email I got about
<P>how this works</P>
<P>Anyway enough of my situation, here is the information:</P>
<P>using inline assembly</P>
<P>Within the C++ language is a keyword </P>
<P>_asm</P>
<P>{</P>
<P>}</P>
Within the block contains the assembly mnemonics/instructions.
<P>There not very hard to use, it usually contains a instruction followed by its operands. The operands usually contain registers, memory,
memory addresses, and constant numbers. Normally in assembly language
every line of code, assembles to one line of machine instructions.
However this isnt always true, there are exceptions. A simple example
of the use of a instruction is the following
<br>
<P>mov eax,1</P>
<P>Now before we can truly really understand this instruction we have
to understand a few other things which are important. Machine languages
are priority languages, and therefore are designed to work for a specific
type of chip. So they work in specific ways and in the x86 chip there are built in high speed memory locations called registers. These registers
are used for data being passed in from memory, or other places to be
manipulated, and then passed back out into memory or other places. Its
kind of like you got to put the information in specific spots it can directly
get to and then setup and call the instruction. What the above example
 means is mov into register eax the hex value 1. The comma separates the
operands. Registers have different sizes, since the registers the cpu's evolved over time. The metaphor Jeff Duntermann makes in his book
which I really recommend it taught me assembly quick and easily is " Assembly Language Step-Step", is " Adding a room to your house doesn't make it two houses--just one bigger house. And so it has been with the x86 registers."
There are multiple types of registers some have specific tasks like the
IP register (Instruction Pointer), Segment Registers, etc. The registers
I am involved with in this example are just the general purpose registers
which I am going to explain here The newer general purpose registers are much more general. In past days
 specific registers had certain agendas but these were actually limitations 
with the cpu. Now days the general purpose registers fall into three classes.
The 32 bit general purpose registers, the 16 bit general purpose registers,
and the 8 bit register halves. What should be noted however is that these
registers are not really 3 distinct separate classes of information. These
names really stand for regions of memory. How this is accomplished is done 
by a little naming system. The 16 bit registers and 8 bit register halves
are really inside the 32 bit registers, and are just specific sections of memory.
In a 32 bit register there are 32 bits. Look at the following graph:
<P> </P>
<P> ax </P>
<P>HI | ah al LOW</P>
<P>1111 1111 1111 1111 1111 1111 1111 1111 - register eax(full 32 bits)</P>
The register eax is the full 32 bits of this memory location. The register 
 ax is the lower half, or the low 16 bits. Register ah is the high half
of the low 16 bits. al is the low 8 bits of ax (the low 16 bits). This
can sound of tricky at first but soon as you understand the notation you
can know how to pick out registers to use with your instructions. Its kind of
 you move stuff from places into the registers, and then use them in accordance 
with instructions, and then move the changes around to different places. Check
out this notation example<br>
<P>General purpose Register eax</P>
<P>eax - full 32 bits</P>
<P> ax - low 16 bits</P>
<P> ah - high 8 bit register half</P>
<P> al - low 8 bit register half</P>
<P>ebx - full 32 bits</P>
<P> bx - low 16 bits</P>
<P> bh - high 8 bit register half</P>
<P> bl - low 8 bit register half</P>
<P>ecx - full 32 bits</P>
<P> cx - low 16 bits</P>
<P> ch - high 8 bit register half</P>
<P> cl - low 8 bit register half</P>
<P>edx - full 32 bits</P>
<P> dx - low 16 bits</P>
<p> dh - high 8 bit register half </p>
 <p> dl - low 8 bit register half </p><br><br>
Now that we understand the notion of the registers we an continue to use
them with memory locations and other types of data. But what were going to explain
here is just inline assembly. Since C++ hides most of its inner workings on how
the actual code is outputted we can literally use C++ variables directly
within your inline assembly. You can create functions that pass variables
that can be manipulated with inline assembly, you can do all
kinds of neat stuff. Here is a simple code snippet:
<P>int __fastcall exampleadd(int x, int y)</P>
<P>{</P>
<P>int rt = 0;</P>
<P>_asm</P>
<P>{</P>
<P>mov eax,x</P>
<P>mov ebx,y</P>
<P>add eax,ebx</P>
<P>mov rt,eax</P>
<P>}</P>
<P>return rt;</P>
<P>}</P>
<P> </P>
This is a function which uses register based calling conventions which are pretty 
 useful when you want just a little bit extra speed. Lets explain the code.
<P>mov eax,x</P>
<P>Means move into register eax (the full 32 bit register) the value within the</P>
<P>variable x (VC when it compiles replaces this with the correct information).</P>
<P>mov ebx,y</P>
<P>Means move into register ebx (the full 32 bit register) the value within the</P>
<P>variable y (VC when it compiles replaces this with the correct information).</P>
<P>add eax,ebx</P>
<P>This means add the integer values in eax , with the values in ebx and put the values</P>
<P>back into eax.</P>
<P>mov rt,eax</P>
<P>Means move the value from register eax into the location where the variable</P>
<P>rt is at.</P>
<P>I hope I gave some light on this subject there's allot of really great tutorials</P>
<P>on the internet if you just look so yeah see ya.</P>
<P>- Jared</P>
<P>PS:</P>
<P> </P>
<P>Here is a simple list of the instruction set I got from opcodes.txt </P>
<P>If your interested in understanding the instructions further I suggest</P>
<P>going and getting a guide to the instruction set. </P>
<P> 8086/80186/80286/80386/80486 Instruction Set</P>
<P> AAA - Ascii Adjust for Addition </P>
<P> AAD - Ascii Adjust for Division </P>
<P> AAM - Ascii Adjust for Multiplication </P>
<P> AAS - Ascii Adjust for Subtraction </P>
<P> ADC - Add With Carry </P>
<P> ADD - Arithmetic Addition </P>
<P> AND - Logical And </P>
<P> ARPL - Adjusted Requested Privilege Level of Selector (286+ PM) </P>
<P> BOUND - Array Index Bound Check (80188+) </P>
<P> BSF - Bit Scan Forward (386+) </P>
<P> BSR - Bit Scan Reverse (386+) </P>
<P> BSWAP - Byte Swap (486+) </P>
<P> BT - Bit Test (386+) </P>
<P> BTC - Bit Test with Compliment (386+) </P>
<P> BTR - Bit Test with Reset (386+) </P>
<P> BTS - Bit Test and Set (386+) </P>
<P> CALL - Procedure Call </P>
<P> CBW - Convert Byte to Word </P>
<P> CDQ - Convert Double to Quad (386+) </P>
<P> CLC - Clear Carry </P>
<P> CLD - Clear Direction Flag </P>
<P> CLI - Clear Interrupt Flag (disable) </P>
<P> CLTS - Clear Task Switched Flag (286+ privileged) </P>
<P> CMC - Complement Carry Flag </P>
<P> CMP - Compare </P>
<P> CMPS - Compare String (Byte, Word or Doubleword) </P>
<P> CMPXCHG - Compare and Exchange </P>
<P> CWD - Convert Word to Doubleword </P>
<P> CWDE - Convert Word to Extended Doubleword (386+) </P>
<P> DAA - Decimal Adjust for Addition </P>
<P> DAS - Decimal Adjust for Subtraction </P>
<P> DEC - Decrement </P>
<P> DIV - Divide </P>
<P> ENTER - Make Stack Frame (80188+) </P>
<P> ESC - Escape </P>
<P> HLT - Halt CPU </P>
<P> IDIV - Signed Integer Division </P>
<P> IMUL - Signed Multiply </P>
<P> IN - Input Byte or Word From Port </P>
<P> INC - Increment </P>
<P> INS - Input String from Port (80188+) </P>
<P> INT - Interrupt </P>
<P> INTO - Interrupt on Overflow </P>
<P> INVD - Invalidate Cache (486+) </P>
<P> INVLPG - Invalidate Translation Look-Aside Buffer Entry (486+) </P>
<P> IRET/IRETD - Interrupt Return </P>
<P> Jxx - Jump Instructions Table </P>
<P> JCXZ/JECXZ - Jump if Register (E)CX is Zero </P>
<P> JMP - Unconditional Jump </P>
<P> LAHF - Load Register AH From Flags </P>
<P> LAR - Load Access Rights (286+ protected) </P>
<P> LDS - Load Pointer Using DS </P>
<P> LEA - Load Effective Address </P>
<P> LEAVE - Restore Stack for Procedure Exit (80188+) </P>
<P> LES - Load Pointer Using ES </P>
<P> LFS - Load Pointer Using FS (386+) </P>
<P> LGDT - Load Global Descriptor Table (286+ privileged) </P>
<P> LIDT - Load Interrupt Descriptor Table (286+ privileged) </P>
<P> LGS - Load Pointer Using GS (386+) </P>
<P> LLDT - Load Local Descriptor Table (286+ privileged) </P>
<P> LMSW - Load Machine Status Word (286+ privileged) </P>
<P> LOCK - Lock Bus </P>
<P> LODS - Load String (Byte, Word or Double) </P>
<P> LOOP - Decrement CX and Loop if CX Not Zero </P>
<P> LOOPE/LOOPZ - Loop While Equal / Loop While Zero </P>
<P> LOOPNZ/LOOPNE - Loop While Not Zero / Loop While Not Equal </P>
<P> LSL - Load Segment Limit (286+ protected) </P>
<P> LSS - Load Pointer Using SS (386+) </P>
<P> LTR - Load Task Register (286+ privileged) </P>
<P> MOV - Move Byte or Word </P>
<P> MOVS - Move String (Byte or Word) </P>
<P> MOVSX - Move with Sign Extend (386+) </P>
<P> MOVZX - Move with Zero Extend (386+) </P>
<P> MUL - Unsigned Multiply </P>
<P> NEG - Two's Complement Negation </P>
<P> NOP - No Operation (90h) </P>
<P> NOT - One's Compliment Negation (Logical NOT) </P>
<P> OR - Inclusive Logical OR </P>
<P> OUT - Output Data to Port </P>
<P> OUTS - Output String to Port (80188+) </P>
<P> POP - Pop Word off Stack </P>
<P> POPA/POPAD - Pop All Registers onto Stack (80188+) </P>
<P> POPF/POPFD - Pop Flags off Stack </P>
<P> PUSH - Push Word onto Stack </P>
<P> PUSHA/PUSHAD - Push All Registers onto Stack (80188+) </P>
<P> PUSHF/PUSHFD - Push Flags onto Stack </P>
<P> RCL - Rotate Through Carry Left </P>
<P> RCR - Rotate Through Carry Right </P>
<P> REP - Repeat String Operation </P>
<P> REPE/REPZ - Repeat Equal / Repeat Zero </P>
<P> REPNE/REPNZ - Repeat Not Equal / Repeat Not Zero </P>
<P> RET/RETF - Return From Procedure </P>
<P> ROL - Rotate Left </P>
<P> ROR - Rotate Right </P>
<P> SAHF - Store AH Register into FLAGS </P>
<P> SAL/SHL - Shift Arithmetic Left / Shift Logical Left </P>
<P> SAR - Shift Arithmetic Right </P>
<P> SBB - Subtract with Borrow/Carry </P>
<P> SCAS - Scan String (Byte, Word or Doubleword) </P>
<P> SETAE/SETNB - Set if Above or Equal / Set if Not Below (386+) </P>
<P> SETB/SETNAE - Set if Below / Set if Not Above or Equal (386+) </P>
<P> SETBE/SETNA - Set if Below or Equal / Set if Not Above (386+) </P>
<P> SETE/SETZ - Set if Equal / Set if Zero (386+) </P>
<P> SETNE/SETNZ - Set if Not Equal / Set if Not Zero (386+) </P>
<P> SETL/SETNGE - Set if Less / Set if Not Greater or Equal (386+) </P>
<P> SETGE/SETNL - Set if Greater or Equal / Set if Not Less (386+) </P>
<P> SETLE/SETNG - Set if Less or Equal / Set if Not greater or Equal </P>
<P> SETG/SETNLE - Set if Greater / Set if Not Less or Equal (386+) </P>
<P> SETS - Set if Signed (386+) </P>
<P> SETNS - Set if Not Signed (386+) </P>
<P> SETC - Set if Carry (386+) </P>
<P> SETNC - Set if Not Carry (386+) </P>
<P> SETO - Set if Overflow (386+) </P>
<P> SETNO - Set if Not Overflow (386+) </P>
<P> SETP/SETPE - Set if Parity / Set if Parity Even (386+) </P>
<P> SETNP/SETPO - Set if No Parity / Set if Parity Odd (386+) </P>
<P> SGDT - Store Global Descriptor Table (286+ privileged) </P>
<P> SIDT - Store Interrupt Descriptor Table (286+ privileged) </P>
<P> SHL - Shift Logical Left </P>
<P> SHR - Shift Logical Right </P>
<P> SHLD/SHRD - Double Precision Shift (386+) </P>
<P> SLDT - Store Local Descriptor Table (286+ privileged) </P>
<P> SMSW - Store Machine Status Word (286+ privileged) </P>
<P> STC - Set Carry </P>
<P> STD - Set Direction Flag </P>
<P> STI - Set Interrupt Flag (Enable Interrupts) </P>
<P> STOS - Store String (Byte, Word or Doubleword) </P>
<P> STR - Store Task Register (286+ privileged) </P>
<P> SUB - Subtract </P>
<P> TEST - Test For Bit Pattern </P>
<P> VERR - Verify Read (286+ protected) </P>
<P> VERW - Verify Write (286+ protected) </P>
<P> WAIT/FWAIT - Event Wait </P>
<P> WBINVD - Write-Back and Invalidate Cache (486+) </P>
<P> XCHG - Exchange </P>
<P> XLAT/XLATB - Translate </P>
<P> XOR - Exclusive OR </P></FONT></BODY>
</HTML>
Original Comments (3)
Recovered from Wayback Machine