ALU Operations

Created

ALU is a "Arithmetic Logic Unit". It is a hardware component within the CPU that does computations on data values.

  • Computations include addition/subtraction and logical operations (shifts, bitwise, and, or, negation, etc).
  • Typically, ALU only operates on integers. The CPU will have floating-point unit(s) for operations for FP values.

Load Effective Address

lea stands for "Load Effective Address."

Instructions that allow a memory reference as an operand generally does a address computation.

  • E.g., movl 12(%rdx, %rsi, 4), %eax. The computed address (for source memory location) is %rdx+(%rsi x 4) + 12
    • 12 is the offset
    • %rdx% is the base
    • %rsi is the index
    • 4 is the scaling

The lea instruction would compute a memory address, but does not access a memory location. - E.g., leaq 12(%rdx, %rsi, 4), %rdi will update the address of %rdi - keep in mind we're not obligated to use the coputer address as an address, we can just use it as an integer. - lea does not set condition codes (e.g., on overflow)

In general, lea can do integer computations of the form p+(qS)+rp+(qS)+r where SS is 0, 1, 2, 4, or 8. if leaq r(p, q, S), <reg>


Example:

/* leaq_example.S */
.section .rodata
sFmt: .string "Result is: %lu\n"

.section .text
        .globl main

main:
        subq $8, %rsp

        movl $0, %eax
        movq $sFmt, %rdi
        movq $1000, %r10
        movq $3, %r11
        leaq 15(%r10,%r11,8), %rsi
        call printf
        addq $8, %rsp
        ret
  • puts 1000 into r10 and 3 into r11
    • leaq 15(%r10,%r11,8), %rsi puts 1000+3*8+15 into %rsi (the second argument).

Addition and Subtraction

add and sub instructions add and subtract integer values.

  • Two operands, second operand is modified to store the result. Note: either operand (but not both) could be a memory refernece.
  • Overflow is possible, and you can detect it using condition code.

Example:

	movq $1, %r9
	movq $2, %r10
	addq %r9, %r10
	/* %r10 now contains the value 3 */

subq %r9, %r10 means to subtract r9 from r10 and store it into r10

Asking for input

/* addsub.S */  
.section .rodata  
sPrompt: .string "Enter an integer value: " sInputFmt: .string "%u"  
sFmt: .string "Result is %u\n"
  • referring to labels without the $ refers to the content, while the $ refers to the address.
.section .data 
val: .space 4
  • .section .data defines a section to store global variables. (we don't know how to put it on the stack yet)
  • val: .space 4 defines a variable and allocates 4 bytes.

Increment and Decrement

inc and dec instructions increment or decrement by 1. One operand, can be either register or memory

  • Overflow is possible, check condition codes

Examples:

incq %rax     /* increment %rax */
incl 4(%rbp)  /* increment 32 bit value at addr %rbp+4 */
decq %rdi     /* decrement %rdi */

Shifts

Left shift: shl

  • shift one position to the left is the same as multiplying by two

Right shift: shr (logical: shfits in zeros) and sar (arithmetic: shifts in the value of the sign bit)

  • shift one position to the right is the same as dividing by two.

Example:

movl $0xFFFF0000, %esi
shll $1, %esi /* %esi set to 0xFFFE0000 */
movl $0xFFFF0000, %esi
sarl $1, %esi /* %esi set to 0xFFFF8000 */
movl $0xFFFF0000, %esi
shrl $1, %esi /* %esi set to 0x7FFF8000 */

Bitwise Logical Operations

Two-operand logical operations: and, or, xor

Unary logical operations: not

Examples:

/* Note: 0x30 = 00110000b,
		0x50 = 01010000b */

movb $0x30, %al; movb $0x50, %bl
andb %bl, %al      /* set %al=0x10 (00010000b) */
movb $0x30, %al; movb $0x50, %bl
orb %bl, %al       /* set %al=0x70 (01110000b) */
movb $0x30, %al; movb $0x50, %bl
xorb %bl, %al      /* set %al=0x60 (01100000b) */
movb $0x30, %al
notb %al           /* set %al=0xCF (11001111b) */

Multiplication

Two forms of imul instruction
Two operand: multiply operands and truncate Example:

imulq %rdi, %rsi  /* set %rsi to %rdi * %rsi, truncated to 64 bits */

One operand: multiply 64 bit operand and value in %rax, 128-bit result in %rdx:%rax

  • Signed (imulq) and unsigned (mulq) variants

Example:

 mulq %rdi/* set %rdx:%rax to unsigned product %rax * %rdi */

Division

idivq and divq: signed and unsigned integer division

128-bit dividend in %rdx:%rax, 64 bit quotient in %rax, 64 bit remainder in %rdx

  • For a 64 bit dividend, set %rdx to 0 (unsigned division) or the replication of the sign bit of %rax (ctqo instruction replicates the sign bit of %rax)

Example:

divq %r10        /* divide %rdx:%rax by %r10, put quotient in %rax, remainder in %rdx */

Memory Conversion

When moving a smaller source vaue to a larger destination, sign-extension (copying sign bit to the high bits) is necessary to preserve the value of a signed value.

  • E.g., the value of -16381 is represented as 1100000000000011 (16 bits) or 11111111111111111100000000000011 (32 bits).

To perform data movement with sign-extension, use movsbw, movsbl, movswl, etc. For unsigned values, data movement with zero-extension (copy 0 into high bits), use movzbw, movzbl, movzwl, etc.

Example:

movzbq %al, %rdi
  • converts 8 bit unit8_t to 64 bit uint64_t