Introduction

Assembly language programs are required when one needs to control hardware directly, without any compiler-generated code coming in between the programmer and the microprocessor.  This has the advantage of speed of execution as well as predictable latencies.  In other words, segments of human-written assembly language code reduces execution time down to the last possible clock cycle. Also, the time for the program control to pass between two checkpoints can be calculated using clock cycle.

The disadvantage of writing programs in Assembly language is tedious and difficult. So for writing larger programs, one prefers to write in high-level languages. C is one such language widely used by programmers who write system software.

Most system software (e.g. the Unix operating system) is written mostly in C, with a few assembly language routines at the core. 95% of the code is in C. The C routines call assembly routines where it must. Sometimes assembly routines call C programs too. One example is where executing assembly language programs up to the point that the execution model required by a C program can be supported does the kernel initializations. From then onwards, the rest of the initialization in C. Therefore, at that point an assembly routine has to call a C routine.

In this project, I will explore the assembly language programming. I will focus on C-callable assembly language programs. I shall use 80X86 (that includes 80386/80486/Pentium/Pentium Pro/MMX/Pentium II microprocessors) based IBM PCs with Linux operating system.

About the Pentium Architecture
1. It is not a load/store architecture.
2. The instruction set is huge!  I can only go over a fraction of the instruction set.
3. There are lots of restrictions on how instructions/operands are put together, but there is also an amazing amount of flexibility.
 
Registers
The Intel architectures as a set just do not have enough registers to satisfy most assembly language programmers.  Still, the processors have been around for a long time, and they have a sufficient number of registers to do whatever is necessary.
For our general-purpose use, I get
32-bit      16-bit    8-bit                            8-bit
                              (high part of 16)                (low part of 16)
EAX         AX        AH                               AL
EBX         BX                BH                               BL
ECX         CX                   CH                               CL
EDX         DX                   DH                           DL
 
    and
 
    EBP                        BP
    ESI                    SI
    EDI                        DI
    ESP                        SP
 
There are a few more, which are not used or discussed in this paper, are only used for memory access ability in the segmented memory model.
 
Using the registers:
As an operand, just use the name (upper case and lower case both work interchangeably).
EBP is a frame pointer.
ESP is a stack pointer.
 
One More Register:
Many bits used for controlling the action of the processor and setting state are in the register called EFLAGS.  This register contains the condition codes:
OF               Overflow flag
SF           Sign flag
ZF           Zero flag
PF                 Parity flag
CF                 Carry flag
 
The settings of these flags are checked in conditional control instructions.  Many instructions set one or more of the flags. There are many other bits in the EFLAGS register.
 
Accessing Memory
There are 2 memory models supported in the Pentium architecture.  In both models, memory is accessed using an address.  It is the way that addresses are formed (within the processor) that differs in the 2 models.
 
Flat Memory Model
In flat memory model, we can do any type of address arithmetic by treating the address as data. We can use the result of the arithmetic as an address to point at anything within the virtual address space. 
 
Segmented Memory Model
1. Different parts of a program are assumed to be in their own, set-aside portions of memory.  These portions are called segments.
2. An address is formed from 2 pieces:  a segment location and an offset within a segment.
Note that each of these pieces can be shorter (contain fewer bits) than a whole address.  This is the reason that Intel chose this form of memory model for its earliest single-chip processors.
3. There are segments for:
       code
       data
       stack
       other
 
Addressing Modes
Some would say that the Intel architectures only support 1 addressing mode.  It looks (something like) this:
                 effective address = base reg + (index reg x scaling factor) + displacement
where
       base reg is                EAX, EBX, ECX, EDX or ESP or EBP
       index reg is             EDI or ESI
       scaling factor is 1, 2, 4, or 8
 
The syntax of using this (very general) addressing mode will vary from system to system.  It depends on the preprocessor and the syntax accepted by the assembler.
For this implementation, an operand within an instruction that uses this addressing mode could look like
                 [EAX][EDI*2 + 80]
The effective address calculated will be the contents of register EDI multiplied 2 added to the constant 80, added to the contents of register EAX.
There are extremely few times where a high-level language compiler can utilize such a complex addressing mode.  It is much more likely that simplified versions of this mode will be used.
 
Register Mode
The operand is in a register.  The effective address is the register.  
Example instruction:
               mov  eax, ecx
Both operands use register mode.  The contents of register ecx  is copied to register eax.
 
Immediate Mode
The operand is in the instruction.  The effective address is within the instruction.  
Example instruction:
               mov  eax, 26
The second operand uses immediate mode.  Within the instruction is the operand. It is copied to register eax.
 
Register Direct Mode
The effective address is in a register.
Example instruction:
               mov  eax, [esp]
The second operand uses register direct mode.  The contents of register esp is the effective address.  The contents of memory at the effective address are copied into register eax.
 
 
Direct Mode
The effective address is in the instruction.
Example instruction:
               mov  eax, var_name
The second operand uses direct mode.  The instruction contains the effective address.  The contents of memory at the effective address are copied into register eax.
 
Base Displacement Mode
The effective address is the sum of a constant and the contents of a register.
Example instruction:
               mov  eax, [esp + 4]
The second operand uses base displacement mode.  The instruction contains a constant.  That constant is added to the contents of register esp to form an effective address.  The contents of memory at the effective address are copied into register eax.
 
Base-Indexed Mode
The effective address is the sum of the contents of two registers.
Example instruction:
               mov  eax, [esp][esi]
The contents of registers, esp and esi, are added to form an effective address.  The contents of memory at the effective address are copied into register eax.
 
PC Relative Mode
The effective address is the sum of the contents of the PC and a constant contained within the instruction.
Example instruction:
               jmp  a_label
The content of the program counter is added to an offset that is within the machine code for the instruction.  The resulting sum is placed back into the program counter.  Note that from the assembly language it is not clear that a PC relative addressing mode is used.  It is the assembler that generates the offset to place in the instruction.
 
Instruction Set
 
Generalities:
1. Many of the instructions have exactly 2 operands.  If there are 2 operands, then one of them will be required to use register mode, and the other will have no restrictions on its addressing mode.
2. There are most often ways of specifying the same instruction for 8-, 16-, or 32-bit operands
 
Meanings of the operand specifications:
               reg                - register mode operand, 32-bit register
               reg8                - register mode operand, 8-bit register
               r/m                - general addressing mode, 32-bit
               r/m8                - general addressing mode, 8-bit
                  immed           - 32-bit immediate is in the instruction
                  immed8         - 8-bit immediate is in the instruction
               m                - symbol (label) in the instruction is the effective address
 
Data Movement
               mov               reg, r/m                 ; copy data
                                  r/m, reg
                                  reg, immed
                                  r/m, immed
               movsx             reg, r/m8                ; sign extend and copy data
               movzx             reg, r/m8                ; zero extend and copy data
               lea                  reg, m                                 ; get effective address
EXAMPLES:
               mov                EAX, 23         ; places 32-bit 2's complement immediate 23 into 
                                                      ;register EAX
               movsx                ECX, AL        ; sign extends the 8-bit quantity in register AL to 32 
                                                      ; bits, and places it in ECX
               mov                [esp], -1          ; places value -1 into memory, address given by 
                                                      ; contents of esp
               lea                EBX, loop_top                ; put the address assigned (by the assembler) to label 
                                                      ; loop_top into register EBX
 
Integer Arithmetic
               add                  reg, r/m                 ; two's complement addition
                                  r/m, reg
                                  reg, immed
                                  r/m, immed
               inc                  reg                             ; add 1 to operand
                              r/m
               sub                  reg, r/m                         ; two's complement subtraction
                                  r/m, reg
                                  reg, immed
                                  r/m, immed
               dec                  reg                                     ; subtract 1 from operand
                              r/m
               neg                  r/m                                  ; get additive inverse of operand
               mul                  eax, r/m                 ; unsigned multiplication edx||eax <- eax * r/m
               imul                  r/m                                    ; 2's comp. Multiplication edx||eax <- eax * r/m
                              reg, r/m                               ; reg <- reg * r/m
                              reg, immed                          ; reg <- reg * immed
               div                  r/m                                     ; unsigned division does edx||eax / r/m, eax <- quotient
                                                      ; edx <- remainder
 
               idiv                  r/m                                 ; 2's complement division does edx||eax / r/m
                                                      ; eax <- quotient, edx <- remainder
 
               cmp                  reg, r/m                             ; sets EFLAGS based on 
                              r/m, immed                         ; second operand - first operand
                              r/m8, immed8 
                              r/m, immed8                   ; sign extends immed8 before subtract 
 
EXAMPLES:
 
                neg                [eax + 4]         ; takes doubleword at address eax+4 and finds its 
                                                      ; additive inverse, then places the additive inverse 
                                                      ; back at that address the instruction should probably 
                                                      ; be 
               neg                 dword ptr [eax + 4]
               inc                ecx                         ; adds one to contents of register ecx, and
                                                        ; result goes back to ecx
 
Logical
               not                  r/m                                    ; logical not
               and                  reg, r/m                               ; logical and
                              reg8, r/m8
                                  r/m, reg
                              r/m8, reg8
                                  r/m, immed
                                  r/m8, immed8
               or                   reg, r/m                            ; logical or
                              reg8, r/m8
                                  r/m, reg
                              r/m8, reg8
                                  r/m, immed
                                  r/m8, immed8
               xor                  reg, r/m                             ; logical exclusive or
                              reg8, r/m8
                                  r/m, reg
                              r/m8, reg8
                                  r/m, immed
                                  r/m8, immed8
 
               test                 r/m, reg                            ; logical and to set EFLAGS
                              r/m8, reg8
                                  r/m, immed
                                  r/m8, immed8
 
EXAMPLES:
               and                edx, 00330000h                ; logical and of contents of register edx (bitwise) 
                                                      ; with 0x00330000, result goes back to edx
 
Floating Point Arithmetic
Since the newer architectures have room for floating point hardware on chip, Intel defined a simple-to-implement extension to the architecture to do floating-point arithmetic.   In their usual zeal, they have included MANY instructions to do floating-point operations.
The mechanism is simple.  A set of 8 registers are organized and maintained (by hardware) as a stack of floating point values.  ST refers to the stack top.  ST(1) refers to the register within the stack that is next to ST.  ST and ST(0) are synonyms.
There are separate instructions to test and compare the values of floating point variables.
 
               finit                                        ; initialize the FPU
 
               fld                  m32                                    ; load floating point value
                              m64 
                              ST(i)
               fldz                                         ; load floating point value 0.0
               fst                  m32                                    ; store floating point value
                              m64 
                              ST(i)
               fstp                 m32                                    ; store floating point value
                              m64                                    ;  and pop ST
                              ST(i)
 
               fadd                 m32                                    ; floating point addition
                              m64
                              ST, ST(i)
                              ST(i), ST
               faddp                ST(i), ST               ; floating point addition and pop ST
 
I/O
The only instructions that actually allow the reading and writing of I/O devices are privileged.  The OS must handle these things.  But, in writing programs that do something useful, we need input and output.  Therefore, there are some simple macros defined to help us do I/O.
These are used just like instructions.
               put_ch            r/m                                      ; print character in the least significant byte of 32-bit 
                                                      ; operand
               get_ch            r/m                          ; character will be in AL
               put_str           m                            ; print null terminated string given by label m
 
Control Instructions
These are the same control instructions that all started with the character 'b' in SASM.
               jmp                  m                              ; unconditional jump
               jg                   m                              ; jump if greater than 0
               jge                  m                              ; jump if greater than or equal to 0
               jl                   m                              ; jump if less than 0
               jle                  m                              ; jump if less than or equal to 0
 

Conclusion

This project provides the basic knowledge of Pentium Assembly Language.  Pentium instruction sets are very large, therefore, further investigation is needed to understand the language.