PROWAREtech

articles » current » assembly » x86 » tutorial » page-11

Intel IA-32 Assembly Tutorial - A Guide to the Basics of x86 Assembly - Page 11

Language Elements (More on Integer Arithmetic: Logical Shifts vs Arithmetic Shifts, More on Instructions: Shift, Rotate, Multiply and Divide).

Integer Arithmetic

This section covers bit shift and bit rotate operations. Because multiplication is a left bit shift operation and division is a right bit shift operation, multiplication and division are covered in this section.

All of the instructions in the table below affect the Overflow and Carry Flags.

Shift and Rotate Instructions
MnemonicDescription
SHLshift left
SHRshift right
SALshift arithmetic left
SARshift arithmetic right
ROLrotate left
RORrotate right
RCLrotate carry left
RCRrotate carry right
SHLDdouble-precision shift left
SHRDdouble-precision shift right

Logical Shifts vs Arithmetic Shifts

A logical shift fills the newly created bit position with zero.

	mov al,10001111b
	shl al,1         ;AL = 00011110b; CF = 1
	mov al,10001111b
	shr al,1         ;AL = 01000111b; CF = 1
	mov al,11010000b
	shr al,1         ;AL = 01101000b; CF = 0

Fast, bit-wise multiplication using SHL is possible when you are multiplying by a base of 2. Shifting an unsigned integer n bits to the left multiplies it by 2n. For example, 8 is 23. Shift 3 to the left is multiply any number by 8.

	mov al,2         ;AL = 00000010b = 2 (02h)
	shl al,3         ;AL = 00010000b = 16 (10h)

Fast, bit-wise division using SHR is possible when you are dividing by a base of 2 operand. For example, 16 is 24. Shift 4 to the right is dividing any number by 16.

	mov al,32        ;AL = 00100000b = 32 (20h)
	shr al,4         ;AL = 00000010b = 2 (02h)

SAL (shift arithmetic left) is identical to SHL.

SAR can be used for signed division. SAR duplicates the sign bit.

	mov al,-128      ;AL = 10000000b = -128 (80h)
	sar al,3         ;AL = 11110000b = -16 (F0h)

The ROL instruction shifts each bit to the left and the highest bit is copied both into the Carry Flag and into the lowest bit. Bit rotation does not lose any bits like bit shifting does.

	mov al,40h       ;AL = 01000000b
	rol al,1         ;AL = 10000000b; CF = 0
	rol al,1		 ;AL = 00000001b; CF = 1
	rol al,1		 ;AL = 00000010b; CF = 0

Use ROL to exchange the upper bits with the lower bits.

	mov al,F1h
	rol al,4         ;AL = 1Fh

The ROR (rotate right) instruction shifts each bit to the right and copies the lowest bit into the Carry Flag and into the highest bit.

	mov al,1         ;AL = 00000001b
	ror al,1         ;AL = 10000000b; CF = 1
	ror al,1         ;AL = 01000000b; CF = 0

The RCL (rotate carry left) instruction shifts each bit to the left, copies the Carry Flag into the least significant bit and copies the most significant bit into the Carry Flag.

	clc              ;CF = 0
	mov bl,88h       ;CF = 0; BL = 10001000b (0 1000 1000)
	rcl bl,1         ;CF = 1; BL = 00010000b (1 0001 0000)
	rcl bl,1         ;CF = 0; BL = 00100000b (0 0010 0001)

Recover a Bit from the Carry Flag: RCL can recover a bit that has previously been shifted into the Carry Flag.

	.data
	byteval BYTE 01101010b
	.code
	shr byteval,1    ;shift least significant bit into Carry Flag
	jc  quit_label   ;jump away if Carry Flag set
	rcl byteval,1    ;otherwise, restore the number

The RCR (rotate carry right) instruction shifts each bit to the right while copying the Carry Flag into the most significant bit and then copies the least significant bit into the Carry Flag.

	stc              ;CF = 1
	mov ah,10h       ;CF = 1; AH = 00010000 (0001 0000 1)
	rcr ah,1         ;CF = 0; AH = 10001000 (1000 1000 0)

Shifting multiple doublewords:

	.data
	ArraySize = 3
	array DWORD ArraySize DUP (99999999h) ;9 = 1001b
	.code
	mov esi,0
	shr array[esi+8],1                    ;high dword
	rcr array[esi+4],1                    ;middle dword, include carry
	rcr array[esi],1                      ;low dword, include carry

The MUL (unsigned multiply) and IMUL (signed multiply) instructions multiply EAX by an operand. The product is stored in EDX and EAX. If, after the operation, EDX is not zero then the Carry Flag is set.

	mov eax,12345h
	mov ebx,10000h
	mul ebx          ;CF = 1, EDX:EAX = 00 00 00 01:23 45 00 00h

The DIV instruction performs division on unsigned integers. A single operand is required and it must be either a register or memory operand. This operand is the divisor. The dividend is the EDX:ECX registers and the quotient is in the EAX register. The remainder is stored in EDX.

	.data
	dividend QWORD 0000000800300020h
	divisor	DWORD 00000100h
	.code
	mov edx,dword ptr dividend + 4 ;high dword
	mov eax,dword ptr dividend     ;low dword
	div divisor                    ;EAX = 08003000h, EDX = 00000020h

Concerning signed integer division... These three instructions are needed. The CBW (convert byte to word) instruction extends the sign bit of AL into the AH register while preserving the number's sign. The CWD (convert word to doubleword) instruction extends the sign bit of the AX register into the DX register. The CDQ (convert doubleword to quadword) instruction extends the sign bit of the EAX register into the EDX register.

	.data
	byteval SBYTE -65  ;9Bh
	wordval SWORD -65  ;FF9Bh
	dwrdval SDWORD -65 ;FFFFFF9Bh
	.code
	mov al,byteval
	cbw                ;AX = FF9Bh
	mov ax,wordval
	cwd                ;DX:AX = FFFF:FF9Bh
	mov eax,dwrdval
	cdq                ;EDX:EAX = FFFFFFFF:FFFFFF9Bh

The IDIV (signed divide) instruction performs signed integer division using the same operands as the DIV instruction, which requires that EAX be sign-extended into EDX using CDQ (convert doubleword into quadword).

	.data
	dwrdval SDWORD -50000
	.code
	mov eax,dwrdval ;dividend low
	cdq             ;extend EAX into EDX
	mov ebx,256     ;divisor
	idiv ebx        ;quotent EAX = -195; remainder EDX = -80

If a divide operation has a quotient that is too large to fit into the destination operand then a divide overflow condition occurs. This and division by zero cause a CPU interrupt and the program halts.

The SHRD (shift right double-precision) and SHLD (shift left double-precision) shifts bits and then replaces them with the second operand based on the number of bits to shift specified in the third operand.

First, it should be made clear that these instructions are not use a lot and they are slow because they take a large number of cpu cycles to execute.

An example of using SHRD to pack data and SHLD to unpack data:


xor esi, esi
mov eax, 100000CCh ; 0001 0000 0000 0000 0000 0000 1100 1100b
mov ebx, 1000004Fh ; 0001 0000 0000 0000 0000 0000 0100 1111b
mov ecx, 10000055h ; 0001 0000 0000 0000 0000 0000 0101 0101b
mov edx, 100000FFh ; 0001 0000 0000 0000 0000 0000 1111 1111b

; pack the data
shrd esi, eax, 3 ; esi = 80000000h = 1000 0000 0000 0000 0000 0000 0000 0000b
shr eax, 3
shrd esi, eax, 3 ; esi = 30000000h = 0011 0000 0000 0000 0000 0000 0000 0000b
shr eax, 3
shrd esi, eax, 2 ; esi = CC000000h = 1100 1100 0000 0000 0000 0000 0000 0000b
shr eax, 2

shrd esi, ebx, 3 ; esi = F9800000h = 1111 1001 1000 0000 0000 0000 0000 0000b
shr ebx, 3
shrd esi, ebx, 3 ; esi = 3F300000h = 0011 1111 0011 0000 0000 0000 0000 0000b
shr ebx, 3
shrd esi, ebx, 2 ; esi = 4FCC0000h = 0100 1111 1100 1100 0000 0000 0000 0000b
shr ebx, 2

shrd esi, ecx, 4 ; esi = 54FCC000h = 0101 0100 1111 1100 1100 0000 0000 0000b
shr ecx, 4
shrd esi, ecx, 4 ; esi = 554FCC00h = 0101 0101 0100 1111 1100 1100 0000 0000b
shr ecx, 4

shrd esi, edx, 1 ; esi = AAA7E600h = 1010 1010 1010 0111 1110 0110 0000 0000b
shr edx, 1
shrd esi, edx, 1 ; esi = D553F300h = 1101 0101 0101 0011 1111 0011 0000 0000b
shr edx, 1
shrd esi, edx, 1 ; esi = EAA9F980h = 1110 1010 1010 1001 1111 1001 1000 0000b
shr edx, 1
shrd esi, edx, 1 ; esi = F554FCC0h = 1111 0101 0101 0100 1111 1100 1100 0000b
shr edx, 1
shrd esi, edx, 4 ; esi = FF554FCCh = 1111 1111 0101 0101 0100 1111 1100 1100b
shr edx, 4

; do something with the packed data

; unpack the data this time using 8-bits this time
shld edx, esi, 8
shl esi, 8
shld ecx, esi, 8
shl esi, 8
shld ebx, esi, 8
shl esi, 8
shld eax, esi, 8
shl esi, 8

; eax = 100000CCh = 0001 0000 0000 0000 0000 0000 1100 1100b
; ebx = 1000004Fh = 0001 0000 0000 0000 0000 0000 0100 1111b
; ecx = 10000055h = 0001 0000 0000 0000 0000 0000 0101 0101b
; edx = 100000FFh = 0001 0000 0000 0000 0000 0000 1111 1111b
<<<[Page 11 of 15]>>>

PROWAREtech

Hello there! How can I help you today?
Ask any question

PROWAREtech

This site uses cookies. Cookies are simple text files stored on the user's computer. They are used for adding features and security to this site. Read the privacy policy.
CLOSE