Chap4 Instructions
Chap4 Instructions
data segment ;data is here the name of the data segment this name may ne changed
..... ;data definitions - DB, DW, DD.
data ends
code segment ;code is here the name of the code segment this name may ne changed
start: mov ax,data
mov ds,ax ;loading the DS segment register with the data segment starting address
...
mov ah,4ch
int 21h ;calling the 4ch function of interrupt 21h for ending
;the run of the current program
code ends
end start ;indicates the end of the source file (the END directive) together with defining
the programs entry point code label start
We may develop programs containing only one data segment and one code segment, having predefined mandatory
names (data and code). For this purpose the simplified directives may be used (TASM only). Such a program has
the following structure:
.model small
.data
. . . ;contents of the data segment
1
.code
Start:
mov ax,@Data
mov ds,ax
. . . ; contents of the code segment
mov ah,4ch
int 21h ;call of 4ch function of 21h interrupt program termination
end Start
where name is a user-defined identifier. In this case the following sequence of MS-DOS commands :
...>TASM name
...>TLINK name
...>TD name
accomplishes the assembling, link-editing and the assisted run of the respective program.
2
XLAT [translation_table] AL <-- < seg:[BX+<AL>] > -
PUSH and POP instructions have the syntax PUSH s and POP d
Operands d and s MUST be words, because the stack is organized on words. The stack grows from big addresses
to small addresses, 2 bytes at a time, SP pointing always to the word from the top of the stack.
The XCHG instruction allows interchanging the contents of two operands having the same size (byte or word), at
least one of them having to be a register. Its syntax is
XCHG operand1, operand2
XLAT "translates" the byte from AL to another byte, using for that purpose a user-defined correspondence table
called translation table. The syntax of the XLAT instruction is
XLAT [translation_table]
translation_table is the direct address of a string of bytes. The instruction requires at entry the far address of the
translation table provided in one of the following two ways:
The effect of XLAT is the replacement of the byte from AL with the byte from the translation table having the
index the initial value from AL (the first byte from the table has index 0). EXAMPLE: pag.111-112 (coursebook).
3
4.1.1.3. Address transfer instructions
These instructions are very useful when operating with strings, for passing parameters etc. In the below table reg
is a general register.
LEA (Load Effective Address) transfers the offset of mem in the destination register. For example
lea ax,v
loads in AX the offset of v, instruction equivalent to mov ax, offset v
But LEA has the advantage that the source operand may be indexed and also registers operands may be used
according to the offset specification formula. For example
lea ax,[bx+v] is NOT equiv. to mov ax, offset [bx+v] (syntax error !)
because OFFSET is an operator and operators impose the evaluations to be made at assembly time.
LDS (Load pointer using DS) and LES (Load pointer using ES) transfer the far address stored in mem (so the
contents of the doubleword variable mem!) in the pair of registers DS:reg and ES:reg respectively. LDS and LES
are an efficient way of preparing in registers the value of some pointers (far addresses of some specific memory
locations).
4
For example, supposing that varp contains the value 1234h:5678h (possibly further interpreted as the far address),
we may obtain the first byte of this memory area in AL by applying the following instruction sequence
. . .
varp dd 12345678h
. . .
lds bx,varp ;transfers the contents of varp in DS:BX - in DS:=1234h and in BX:=5678h
mov al,[bx] ;transfers in AL the byte from DS:[BX], namely the byte from 1234h:5678h
We notice very much confusion regarding the mechanisms involved by LDS and LES relatively to that of LEA.
Because all 3 of them are presented as address transfer instructions and because it is easy to understand the
effect of LEA, there is a temptation to infere that LDS and LES are similar to LEA, in the sense that they will not
load ONLY the offset of the source operand (as LEA does) but (and now there is a mistaken interpretation!!!) they
will transfer the whole far address (segment:offset) of the source operand! Here comes up the very frequent
interpretation mistake done : LDS and LES do NOT transfer the far address of the source operand, but ITS
CONTENTS !
It is very important not to get into confusion and thinking in terms of LEA and to interpret that the effect of the
above instruction to be the transfer of the varp address in ds:bx (INCORRECT conclusion !!!). If we really
wanted something like that , the correct solution is :
; the following sequence loads in ds:bx the far address of the varp variable!
mov ax, SEG varp ;the SEG operatorul was introduced in 3.2.2.7.
mov ds,ax ;transfers the segment address of varp in DS
lea bx, varp ;transfer the offset of varp in BX
6
4.1.1.4. Flag instructions
LAHF (Load register AH from Flags) copies SF, ZF, AF, PF and CF from FLAGS register in the bits 7, 6, 4, 2
and respectively 0 of register AH. The contents of bits 5,3 and 1 is undefined. Other flags are not affected
(meaning that LAHF does not generate itself other effects on some other flags it just transfers the flags values
and thats all).
SAHF (Store register AH into Flags) transfers the bits 7, 6, 4, 2 and 0 of register AH in SF, ZF, AF, PF and CF
respectively, replacing the previous values of these flags.
PUSHF transfers all the flags on top of the stack (the contents of the FLAGS register is transferred onto the stack)
POPF extracts the word from top of the stack and transfer its contents into the FLAGS register.
Also, the 8086 assembly language offers instructions for setting the values for 3 of the 9 existing flags.
CLC CF=0 CF
CMC CF = ~CF CF
STC CF=1 CF
CLD DF=0 DF
STD DF=1 DF
CLI IF=0 IF
7
STI IF=1 IF
CBW converts the signed byte from AL to the signed word AX (extends the sign bit of the byte from AL into the
whole AH). For example,
mov al, -1
cbw ;extends the byte value -1 from AL to the word value -1 in AX.
Similarly, for the signed conversion word - doubleword, CWD extends the signed word from AX to the signed
doubleword in DX:AX. Example:
mov ax,-10000
cwd ;obtains the value -10000 in DX:AX.
The unsigned conversion is done by zerorizing the higher byte or word of the initial value:
8
4.1.3. The impact of the little-endian representation on accessing data (pag.119 122 coursebook).
If the programmer uses data consistent with the size of representation established at definition time then assembly
language instructions will automatically take into account the details of representation (they will manage
automatically the little-endian memory layout). If so, the programmer must not provide any source code measures
for assuring the correctness of data management. Example:
a db d, -25, 120
b dw -15642, 2ba5h
c dd 12345678h
mov al, a ;loads in AL the ASCII code of d
mov bx, b ;loads in BX the value -15642; the order of bytes in BX will be reversed
compared to the memory representation of b, because only the memory representation uses little-
endian! At register level data is stored according to the usual structural representation (equiv.to a
big endian representation).
les dx, c ; loads in ES:DX the doubleword value 1234:5678h ; in ES - 1234h ; in DX - 5678h.
; the memory layout for c is 78h 56h 34h 12h ; after les the order of bytes in the
registers
; will be the normal structural one , namely 12h 34h 56h 78h.
If we need accessing or interpreting data in a different form than that of definition then we must use explicit type
conversions. In such a case, the programmer must assume the whole responsability of correctly accessing and
9
interpreting data. In such cases the programmer must be aware of the little-endian representation details (the
particular memory layout corresponding to that variable/memory area) and use proper and consistent accesing
mechanisms Ex pag.120-122.
4.2. OPERATIONS
Operands are represented in complementary code (see 1.5.2.). The microprocessor performs additions and
substractions "seeing" only bits configurations, NOT signed or unsigned numbers. The rules of binary adding or
substracting two numbers do not impose previously considering the operands as signed or unsigned, because
independently of interpretation, additions and subtractions works the same way. So, at the level of these
operations, the signed or unsigned interpretation depends on a further context and is left to the programmer. These
means that NO special signed addition or signed subtraction instructions are needed (no need for IADD or
ISUB).
A = 9Ch = 10011100b (= 156 in the unsigned interpretation and -100 in the signed interpretation)
B = 4Ah = 01001010b (= 74 , both in signed and unsigned interpretation)
C = E6h = 11100110b (= 230 in the unsigned interpretation and -26 in the signed one)
We though notice that the simple addition of the bits configuration (without taking into account a certain
interpretation at the moemnt of addition) assures the result correctness, both in signed and unsigned
interpretation.
10
ARITHMETIC INSTRUCTIONS pag.123 (coursebook)
4.2.2. Logical bitwise operations (AND, OR, XOR and NOT instructions).
AND is recommended for isolating a certain bit or for forcing the value of some bits to 0.
OR is suitable for forcing certain bits to 1.
XOR is suitable for complementing the value of some bits.
11
RCL X,1 ;has the effect X = bcdefghk and CF = a
RCR X,1 ;has the effect X = kabcdefg and CF = h
INSTRUCTIONS FOR BITS SHIFTING AND ROTATING pag.134 (coursebook)
mov ax,1
jmp AdunaDoi
AdunaUnu: inc ax
jmp urmare
AdunaDoi: add ax,2
urmare: . . .
12
AX will hold the value 3. inc i jmp betwwen AdunaUnu and AdunaDoi will not be executed.
As mentioned above, the jump may be made to an address stored in a register or in a memory variable. Examples:
If in case (1) we wish to replace the register destination operand with a memory variable destination operand, a
possible solution is:
b dw ?
(1) ...
mov b, offset etich
jmp b ; NEAR jump memory variable operand
JMP may also be used for transferring the control in another code segment (far jump). In such a case the target
address must be identified as a FAR one (segment:offset).
a). declaring the destination label as FAR label using the LABEL directive (see 3.3.3). Example pag.140.
13
b). directly specifying in the JMP instruction the FAR PTR type for the destination label as: JMP FAR PTR label.
Such a specification has been used in 3.3.1.2 the ASSUME directive. The PTR operator - 3.2.2.7.
c). explicitly prefixing with a segment register a NEAR address specified indirectly, namely reg_segment:
specificare_offset. Example: jmp es:[bx+di].
d). specifying as an operand a doubleword variable containing the far address of destination (pag.141).
Exemplul 4.3.1.2. pag.142-143 (coursebook) control transfer to a label. Analysis and comparison between
direct transfer indirect transfer.
Conditional jump instructions are usually used combined with comparision instructions. Thus, the semantics of
jump instructions follow the semantics of a comparision instruction. Besides the equality test performed by a
CMP instruction we need frequently to determine the exact order relationship between 2 values. For example we
have to answer to: nr. 11111111b (= FFh = 255 = -1) is bigger than 00000000b(= 0h = 0)? The answer is .... IT
DEPENDS !!!! This answer can be either YES or NO ! If we perform an unsigned comparision, then the first one
is 255 and is obvious bigger than 0. If the 2 values are compared in the signed interpretation, then the first is -1
and is less than 0.
The CMP instruction does not make any difference between the two above cases, because addition and
subtraction are performed always in the same way (adding or subtracting binary configurations) no matter their
interpretations (signed or unsigned). So its not the matter to interpret the operands of CMP as being signed or
14
unsigned, but to further interpret the RESULT of the subtraction ! Conditional jump instruction are in charge to do
that.
4.3.2.2. Conditional jumps
Table 4.1. (pag.146 coursebook) presents the conditional jump instructions together with their semantics and
according to which flags values the jumps are made. For all the conditional jump instructions the general syntax is
<conditional_jump_instruction> label
The effect of the conditional jump instructions is expressed as "jump if operand1 <<relationship>> operand2"
(where on the two operands a previously CMP or SUB instruction is supposed to have been applied) or relative to
the actual value set for a certain flag. As easy can be noticed based on the conditions that must be verified,
instructions on the same line in the table have similar effect.
When two signed numbers are compared, "less than" and "greater than" terms are used and when two
unsigned numbers are compared "below" and "above" terms are respectively used.
- Comparative analysis and discussion on : signed representations vs. unsigned, overflow, actual effects of
conditional jump instructions.
<instruction> label
15
LOOP performs the repetitive run of the instructions block starting at label, as long as the contents of CX register
is not 0. It first performs decrementation of CX, then the test vs. 0 and then the jump if the result is not 0.
The jump is a NEAR one (max. 127 bytes so pay attention to the "distance" between LOOP and the label!).
When the end of loop conditions are more complex LOOPE and LOOPNE may be used. LOOPE (LOOP
while Equal) ends the loop either if CX=0, either if ZF=1. LOOPNE (LOOP while Not Equal) ends the loop
either if CX=0, either if ZF=0. Even if the loop exit is done based on ZF, CX decrementation is done anyway.
LOOPE is the same as LOOPZ and LOOPNE the same as LOOPNZ. These are usually used preceeded by a
CMP or SUB instruction.
JCXZ (Jump if CX is Zero) performs the jump to the specified label only if CX=0, being useful when we want to
test the value from CX before entering the loop. The example below shows why JCXZ is useful for avoiding
enetring the loop with CX=0:
. . .
jcxz MaiDeparte ;if CX=0 a jump over the loop is made
Bucla:
Mov BYTE PTR [si],0 ;initializing the current byte
inc si ;passing to the next byte
loop Bucla ;resume the loop or ending it
MaiDeparte: . . .
If a loop is entered with CX=0, CX is first decremented, obtaining the value 0FFFFh (= -1, so diff. from 0, but
also 65535 in the unsigned interpretation), the loop being resumed until 0 in CX will be reached, namely 65535
times !
16
4.3.4. CALL and RET
A procedure call is done by using the CALL instruction (direct or indirect call). The direct call has the syntax
CALL operand
Similar to JMP, CALL transfers the control to the address specified by the operand. In addition to JMP, before
performing the jump, CALL saves to the stack the address of the instruction following CALL (the returning
address). In other words, we have the equivalence :
The end of the called sequence is marked by a RET instruction. This pops from the stack the returning address
stored there by CALL, transferring the control to the instruction from this address. The RET syntax is
RET [n]
where n is an optional parameter. If present, it frees also from the stack n bytes below the returning address.
B dw ?
RET n . . .
(near return) pop B
add sp,n
jmp B
17
B dd ?
RET n . . .
(far return) pop word ptr B
pop word ptr B+2
add sp,n
jmp B
name PROC
. . .
ret [n]
name ENDP
. . .
CALL name
PROC and ENDP were discussed in 3.3.4. The call and return are implicitly far or near, dependent on how
procedure name is declared FAR or NEAR respectively.
CALL may also take the transfer address from a register (for an intrasegment call) or from a memory variable.
Such a call is identified as an indirect call. Example:
19