570 likes | 715 Views
Machine-Level Programming II: Arithmetic & Condition Codes Comp 21000: Introduction to Computer Organization & Systems March 2014 Systems book chapter 3*. * Modified slides from the book “Computer Systems: a Programmer’s Perspective”, Randy Bryant & David O’Hallaron , 2011. Today.
E N D
Machine-Level Programming II: Arithmetic & Condition CodesComp 21000: Introduction to Computer Organization & SystemsMarch 2014Systems book chapter 3* * Modified slides from the book “Computer Systems: a Programmer’s Perspective”, Randy Bryant & David O’Hallaron, 2011
Today • Complete addressing mode, address computation (leal) • Arithmetic operations • Control: Condition codes • Conditional branches • While loops
Complete Memory Addressing Modes • Most General Form • D(Rb,Ri,S) Mem[Reg[Rb]+S*Reg[Ri]+ D] • D: Constant “displacement” 1, 2, or 4 bytes • Rb: Base register: Any of 8 integer registers • Ri: Index register: Any, except for %esp • Unlikely you’d use %ebp, either • S: Scale: 1, 2, 4, or 8 (why these numbers?) • Special Cases • (Rb,Ri) Mem[Reg[Rb]+Reg[Ri]] • D(Rb,Ri) Mem[Reg[Rb]+Reg[Ri]+D] • (Rb,Ri,S) Mem[Reg[Rb]+S*Reg[Ri]]
lealSrc,Dest Src is address mode expression Set Dest to address denoted by expression Format Looks like a memory access Does not actually access memory Rather, calculates the memory address, then stores in a register Uses Computing addresses without a memory reference E.g., translation of p = &x[i]; Computing arithmetic expressions of the form x + k*y k = 1, 2, 4, or 8. Address Computation Instruction lea = load effective address
Example Converted to ASM by compiler: int mul12(int x) { return x*12; } leal (%eax,%eax,2), %eax ;t <- x+x*2 sall $2, %eax ;return t<<2 ; or t * 4
Today • Complete addressing mode, address computation (leal) • Arithmetic operations • Control: Condition codes • Conditional branches • While loops
Some Arithmetic Operations • Two Operand Instructions: FormatComputation addlSrc,DestDest = Dest + Src sublSrc,DestDest = DestSrc imullSrc,DestDest = Dest * Src sallSrc,DestDest = Dest << SrcAlso called shll sarlSrc,DestDest = Dest >> SrcArithmetic shrlSrc,DestDest = Dest >> SrcLogical xorlSrc,DestDest = Dest ^ Src andlSrc,DestDest = Dest & Src orlSrc,DestDest = Dest | Src • Watch out for argument order! • No distinction between signed and unsigned int (why?) • No way to store result in different register in the instruction. • Note the order: Dest is subtracted from
Some Arithmetic Operations • One Operand Instructions inclDestDest = Dest + 1 declDestDest = Dest1 neglDestDest = Dest notlDestDest = ~Dest • See book for more instructions
Arithmetic Expression Example arith: pushl %ebp movl %esp, %ebp movl 8(%ebp), %ecx movl 12(%ebp), %edx leal (%edx,%edx,2), %eax sall $4, %eax leal 4(%ecx,%eax), %eax addl %ecx, %edx addl 16(%ebp), %edx imull %edx, %eax leave ret Set Up intarith(int x, int y, int z) { int t1 = x+y; int t2 = z+t1; int t3 = x+4; int t4 = y * 48; int t5 = t3 + t4; intrval = t2 * t5; return rval; } Body Finish this is similar to what you’d see with optimization level 1 With optimization level 0 you won’t see lea instructions
Understanding arith intarith(int x, int y, int z) { int t1 = x+y; int t2 = z+t1; int t3 = x+4; int t4 = y * 48; int t5 = t3 + t4; intrval = t2 * t5; return rval; } Offset %ebp movl 8(%ebp), %ecx movl 12(%ebp), %edx leal (%edx,%edx,2), %eax sall $4, %eax leal 4(%ecx,%eax), %eax addl %ecx, %edx addl 16(%ebp), %edx imull %edx, %eax
Understanding arith Stack intarith(int x, int y, int z) { int t1 = x+y; int t2 = z+t1; int t3 = x+4; int t4 = y * 48; int t5 = t3 + t4; intrval = t2 * t5; return rval; } Offset %ebp movl 8(%ebp), %ecx # ecx = x movl 12(%ebp), %edx # edx = y leal (%edx,%edx,2), %eax # eax = y*3 sall $4, %eax # eax*= 16 (t4) leal 4(%ecx,%eax), %eax # eax = t4 +x+4 (t5) addl %ecx, %edx # edx = x+y (t1) addl 16(%ebp), %edx # edx += z (t2) imull %edx, %eax # eax = t2 * t5 (rval)
Observations about arith intarith(int x, int y, int z) { int t1 = x+y; int t2 = z+t1; int t3 = x+4; int t4 = y * 48; int t5 = t3 + t4; intrval = t2 * t5; return rval; } • Instructions in different order from C code • Some expressions require multiple instructions • Some instructions cover multiple expressions • Get exact same code when compile: • (x+y+z)*(x+4+48*y) movl 8(%ebp), %ecx # ecx = x movl 12(%ebp), %edx # edx = y leal (%edx,%edx,2), %eax # eax = y*3 sall $4, %eax # eax*= 16 (t4) leal 4(%ecx,%eax), %eax # eax = t4 +x+4 (t5) addl %ecx, %edx # edx = x+y (t1) addl 16(%ebp), %edx # edx += z (t2) imull %edx, %eax # eax = t2 * t5 (rval)
Another Example • logical: • pushl %ebp • movl %esp,%ebp • movl12(%ebp),%eax • xorl8(%ebp),%eax • sarl $17,%eax • andl $8185,%eax • popl %ebp • ret Set Up int logical(int x, int y) { int t1 = x^y; int t2 = t1 >> 17; int mask = (1<<13) - 7; intrval = t2 & mask; return rval; } Body Finish movl12(%ebp),%eax # eax = y xorl8(%ebp),%eax # eax = x^y (t1) sarl $17,%eax # eax = t1>>17 (t2) andl $8185,%eax # eax = t2 & mask (rval)
Another Example • logical: • pushl %ebp • movl %esp,%ebp • movl12(%ebp),%eax • xorl8(%ebp),%eax • sarl $17,%eax • andl $8185,%eax • popl %ebp • ret Set Up int logical(int x, int y) { int t1 = x^y; int t2 = t1 >> 17; int mask = (1<<13) - 7; intrval = t2 & mask; return rval; } Body Finish movl12(%ebp),%eax # eax = y xorl8(%ebp),%eax # eax = x^y (t1) sarl $17,%eax # eax = t1>>17 (t2) andl $8185,%eax # eax = t2 & mask (rval)
Another Example • logical: • pushl %ebp • movl %esp,%ebp • movl12(%ebp),%eax • xorl8(%ebp),%eax • sarl $17,%eax • andl $8185,%eax • popl %ebp • ret Set Up int logical(int x, int y) { int t1 = x^y; int t2 = t1 >> 17; int mask = (1<<13) - 7; intrval = t2 & mask; return rval; } Body Finish movl12(%ebp),%eax # eax = y xorl8(%ebp),%eax # eax = x^y (t1) sarl $17,%eax # eax = t1>>17 (t2) andl $8185,%eax # eax = t2 & mask (rval)
Another Example • logical: • pushl %ebp • movl %esp,%ebp • movl12(%ebp),%eax • xorl8(%ebp),%eax • sarl $17,%eax • andl $8185,%eax • popl %ebp • ret Set Up int logical(int x, int y) { int t1 = x^y; int t2 = t1 >> 17; int mask = (1<<13) - 7; intrval = t2 & mask; return rval; } Body Finish 213 = 8192, 213 – 7 = 8185 movl12(%ebp),%eax # eax = y xorl8(%ebp),%eax # eax = x^y (t1) sarl $17,%eax # eax = t1>>17 (t2) andl $8185,%eax # eax = t2 & mask (rval)
Today • Complete addressing mode, address computation (leal) • Arithmetic operations • Control: Condition codes • Conditional branches • Loops
%eax %ecx %edx %ebx %esi %edi %esp %ebp Processor State (IA32, Partial) • Information about currently executing program • Temporary data( %eax, … ) • Location of runtime stack( %ebp,%esp ) • Location of current code control point( %eip, … ) • Status of recent tests( CF, ZF, SF, OF ) General purpose registers Current stack top Current stack frame Instruction pointer %eip CF ZF SF OF Condition codes
Condition Codes (Implicit Setting) • Single bit registers CF Carry Flag (for unsigned) SFSign Flag (for signed) ZF Zero Flag OFOverflow Flag (for signed) • Implicitly set (think of it as side effect) by arithmetic operations Example: addl/addqSrc,Dest ↔ t = a+b CF set if carry out from most significant bit (unsigned overflow) ZF set if t == 0 SF set if t < 0 (as signed) OF set if two’s-complement (signed) overflow(a>0 && b>0 && t<0) || (a<0 && b<0 && t>=0) • Not set by lea instruction • Full documentation (IA32), link on course website
Condition Codes • Examples: assume %eax contains 20 addl $10, %eax CF 0 ZF 0 SF 0 OF 0 subl $50, %eax CF 0 ZF 0 SF 1 OF 0
Condition Codes • Single Bit Registers CF Carry Flag SF Sign Flag ZF Zero Flag OF Overflow Flag • Also implicitly Set By logical Operations xorlSrc,Dest C analog: t = a ^ b (a = Src, b = Dest) • CF set to 0 • ZF set if t == 0 • SF set if t < 0 • OF set to 0 • For shift operations: • CF set to last bit shifted out • OF set to 0
Condition Codes (Implicit Setting) • There are no Boolean types in assembly language. • There is no concept of Boolean operators in assembly language. • So what is there? • Bits • All we can do is look at bits. What those bits mean is determined by the context of the program. • Instructions set flags. • Other instructions take action based on the bits in those flags. • Don’t think about it as comparison as in the C language sense.
Condition Codes (Explicit Setting: Compare) • Explicit Setting by Compare Instruction • cmpl/cmpqSrc2, Src1 • cmplb,a like computing a-b without setting destination • CF set if carry out from most significant bit (used for unsigned comparisons) • ZF set if a == b • SF set if (a-b) < 0 (as signed) • OF set if two’s-complement (signed) overflow(a>0 && b<0 && (a-b)<0) || (a<0 && b>0 && (a-b)>0) Note: notice that the operands are in reverse order; b is the first operand , but we compute a – b! Note 2: there are also cmpw and cmpb instructions.
Example cmpl %eax, %ecx do %ecx - %eax then set condition codes NO other action taken! Condition codes CF ZF SF OF ?? ?? ?? ??
Example cmpl %eax, %ecx do %ecx - %eax then set condition codes NO other action taken! Condition codes CF ZF SF OF 0 0 0 0
Condition Codes (Explicit Setting: Test) • Explicit Setting by Test instruction • testl/testqSrc2, Src1testlb,a like computing a&b without setting destination • Sets condition codes based on value of Src1 & Src2 • Useful to have one of the operands be a mask • CF set to 0 • ZF set when a&b == 0 • SF set when a&b < 0 • OF set to 0 Note: typically the same operand is repeated to test whether it is negative, zero, or positive: testl %eax, %eax sets the condition codes depending on the value in %eax Note 2: there are also testw and testb instructions. • Remember that bitwise operations are more efficient than arithmetic
Reading Condition Codes • SetXInstructions (the ‘X’ is replaced by some letter) • Set single byte (with 0x00 or 0x01) based on combinations of condition codes • The first instruction that reacts to a condition code!
Reading condition codes • Consider: setlD (SF^OF) Less (Signed <) D(SF^OF) • First compare two numbers, a and b where both are in 2’s complement form using an arithmetic, logical, test or cmp instruction • Then use setX to set a register with the result of the test cmpl %eax, %edx setl %al puts the result in byte register %al
Reading condition codes (cont) • Assume a is in %eax and b in %edx cmpl %eax, %edx setl %al puts the result in byte register %al • First instruction sets the condition code. • cmpl computes b – a • If b< a then b – a < 0 If there is no overflow, this is indicated by SF • If there is positive overflow (b – a is large), we have b – a < 0 but OF is set • If there is negative overflow (b – a is very small), we have b – a > 0 but OF is set • In either case the sign flag will indicate the opposite of the sign of the true difference. Hence, use exclusive-or of the OF and SF • Second instruction sets the %al register to 00000000 or 00000001 depending on the value of (SF^OF) • setl D ; D (SF^OF)
Reading condition codes (cont) • Example: assume %eax holds 20 and %edx holds 50 cmpl %eax, %edx 50 – 20, SF 0, OF 0 setl %al %al 0 ^ 0 = 00000000 • Example: assume %eax holds 0x8000001 and %edx holds 20 cmpl %eax, %edx 20 – (-2147483647) , SF 1, OF 1 setl %al %al 1 ^ 1 = 00000000 setl gives false; 20 is not less than -2147483647 • setl D ; D (SF^OF)
Reading condition codes (cont) • Example: assume %eax holds 20 and %edx holds 0x8000001 cmpl %eax, %edx (-2147483647) - 20 , SF 0, OF 1 0x80000001 + 0xFFFFFFEC = 0x7FFFFFED (note that 7 = 0111) setl %al %al 0 ^ 1 = 00000001 setl gives true; -2147483647 is less than 20
SetgGreater (Signed) ~(SF^OF)&~ZF ~SF&~OF If this is zero, can’t be > First do an arith, logical, cmp or test. Then use the flags If the overflow flag is set, can’t be > if we did a cmpl or testlas the previous instruction. Why? CF ZF SF OF Condition codes
Reading Condition Codes (Cont.) • SetXInstructions (where X = g, l, le, etc): • Set single byte(with 0x01) based on combination of condition codes • One of 8 addressable byte registers • Does not alter remaining 3 bytes • Typically use movzbl to finish job Stack Offset intgt (int x, int y) { return x > y; } Body %ebp movl 12(%ebp),%eax # eax = y cmpl %eax,8(%ebp) # Compare x - y setg %al # al = x > y movzbl %al,%eax # Zero rest of %eax
• • • Stack Offset 16 12 y 8 x 4 Rtnadr %ebp 0 Old %ebp Reading Condition Codes (Cont.) intgt (intx, inty) { return x > y; } %eax %ah %al %edx %dh %dl %ecx %ch %cl %ebx %bh %bl All 0’s: 0000000000000000000000000 %esi %edi Either 00000000 or 00000001 %esp %ebp Body movl 12(%ebp),%eax # eax = y cmpl %eax,8(%ebp) # Compare x : y setg %al # al = x > y movzbl %al,%eax # Zero rest of %eax
Reading Condition Codes (Cont.) intgt (int x, int y) { return x > y; } • To walk through this code in gdb: • Compile with –g flag • In gdb Set breakpoint e.g. at line 5 • to see assembly code: disassemble gt • run Then step through assembly code with nexti • Examine registers with p/x $eax or for all registers: info registers • To see which flags are set: info register eflags • To determine where you are: (gdb) where #0 0x0000000100000e45 in gt (x=5, y=4) at setEx.c:5 #1 0x0000000100000e8f in main at setEx.c:14 $ not % One line of C may translate to many lines of assembly 0x0000000100000e42 <gt+10>: movl 12(%ebp),%eax 0x0000000100000e45 <gt+13>: cmpl %eax,8(%ebp) 0x0000000100000e48 <gt+16>: setg %al 0x0000000100000e4b <gt+19>: movzbl %al,%eax
Reading Condition Codes: x86-64 • SetX Instructions: • Set single byte based on combination of condition codes • Does not alter remaining 3 bytes intgt (long x, long y) { return x > y; } long lgt (long x, long y) { return x > y; } Bodies cmpl %esi, %edi setg %al movzbl %al, %eax cmpq%rsi, %rdi setg %al movzbl %al, %eax Is %raxzero? Yes: 32-bit instructions set high order 32 bits to 0!
Today • Complete addressing mode, address computation (leal) • Arithmetic operations • x86-64 • Control: Condition codes • Conditional branches & Moves • Loops
Jumping • A jump instruction causes execution to jump to a new address • Really just puts the argument of the jump into the EIP • Jump destinations are usually indicated by a label • A label marks a place in code 1 xorl %eax, %eax 2 jmp .L1 3 movl (%eax), %edx 4 .L1: popl %edx • The instruction jmp .L1 causes program to skip line 3 • jmp is an unconditional jump instruction • Note that we wouldn’t really use the code this way!
Jumping • A jump instruction has two types of arguments • Direct jumps. Target is part of the instruction • Use a label • Indirect jumps. Target read from a register or memory. • Use a ‘*’ followed by an operand specifier jmp *%eax or jmp *(%eax) • Any addressing mode can be used • Note that jmp is an unconditional jump instruction
Jumping • Other jump instructions are conditional • Either jump or continue executing at next instruction in the code • Depends on some combination of the condition codes • Names and conditions match the set instructions. • Conditional jumps can only be direct • Assembler changes labels into actual memory addresses • See section 3.6.3 of the book • Not very important now; will be very important in chapter 7
Jumping • jX Instructions • Jump to different part of code depending on condition codes
jgGreater (Signed) ~(SF^OF)&~ZF ~SF&~OF If this is zero, can’t be > First do an arith, logical, cmp or test. Then use the flags If the overflow flag is set, can’t be > if we did a cmpl or testlas the previous instruction. Why? CF ZF SF OF Condition codes
Compiling code • Reminder. You can obtain the assembly code with the command: • gcc–O0 –m32 –S source.c • Produces file code.s-S means stop after compiling • If you want to gdb use the following command • gcc -O0 -m32 -g -o executableNamesourceName.c Use the –g flag to have gcc generate the symbol table information that gdb will need. Use the –o0 flag (dash uppercase ‘O’ number zero) to eliminate optimization. Otherwise you’ll get strange register moving. Use the –m32 flag to have gcc generate IA32 assembly (as opposed to 64 bit code)
• • • Stack Offset 12 y 8 x 4 Rtn adr %ebp 0 Old %ebp Conditional Branch Example intabsdiff(int x, int y) { int result; if (x > y) { result = x-y; } else { result = y-x; } return result; } absdiff: pushl %ebp movl %esp, %ebp movl 8(%ebp), %edx movl 12(%ebp), %eax cmpl %eax, %edx jle .L6 subl %eax, %edx movl %edx, %eax jmp .L7 .L6: subl %edx, %eax .L7: popl %ebp ret Setup x stored in %edx y stored in %eax Body1 Body2a Body2b Finish
Conditional Branch Example (Cont.) intgoto_ad(int x, int y) { int result; if (x <= y) gotoElse; result = x-y; goto Exit; Else: result = y-x; Exit: return result; } • C allows “goto” as means of transferring control • Closer to machine-level programming style • Generally considered bad coding style absdiff: pushl %ebp movl %esp, %ebp movl 8(%ebp), %edx movl 12(%ebp), %eax cmpl %eax, %edx jle .L6 subl %eax, %edx movl %edx, %eax jmp .L7 .L6: subl %edx, %eax .L7: popl %ebp ret Setup Body1 x - y Body2a Body2b Finish
Conditional Branch Example (Cont.) intgoto_ad(int x, int y) { int result; if (x <= y) gotoElse; result = x-y; goto Exit; Else: result = y-x; Exit: return result; } absdiff: pushl %ebp movl %esp, %ebp movl 8(%ebp), %edx movl 12(%ebp), %eax cmpl %eax, %edx jle .L6 subl %eax, %edx movl %edx, %eax jmp .L7 .L6: subl %edx, %eax .L7: popl %ebp ret Setup Body1 Body2a Body2b Finish
Conditional Branch Example (Cont.) intgoto_ad(int x, int y) { int result; if (x <= y) gotoElse; result = x-y; goto Exit; Else: result = y-x; Exit: return result; } absdiff: pushl %ebp movl %esp, %ebp movl 8(%ebp), %edx movl 12(%ebp), %eax cmpl %eax, %edx jle .L6 subl %eax, %edx movl %edx, %eax jmp .L7 .L6: subl %edx, %eax .L7: popl %ebp ret Setup Body1 Body2a Body2b Finish
Conditional Branch Example (Cont.) intgoto_ad(int x, int y) { int result; if (x <= y) gotoElse; result = x-y; goto Exit; Else: result = y-x; Exit: return result; } absdiff: pushl %ebp movl %esp, %ebp movl 8(%ebp), %edx movl 12(%ebp), %eax cmpl %eax, %edx jle .L6 subl %eax, %edx movl %edx, %eax jmp .L7 .L6: subl %edx, %eax .L7: popl %ebp ret Setup Body1 Body2a Body2b Finish