void putchar(char); #define N 10 int in[N] = {10, 32, -1, 567, 3, 18, 1, -51, 789, 0}; |
; PDP-11 assembly generated by lcc 4.2 ; assemble with MACRO-11 .INCLUDE /LCC.MLB/ .RADIX 10 fp=%5 ; R5 is frame pointer .ENABL LSB ; file-wide local symbols .GLOBL in in: .WORD 10 .WORD 32 .WORD -1 .WORD 567 .WORD 3 .WORD 18 .WORD 1 .WORD -51 .WORD 789 .WORD 0 |
|
/* exchange - exchange *x and *y */ void exchange(x, y) int *x, *y; { int t; t = *x; *x = *y; *y = t; } There is an extra MOV in the code that I can't prevent lcc from generating. It seems to want to put x in a temporary register, but actually makes the code worse. The function should consist of just three MOVs. |
.GLOBL exchange .SBTTL exchange exchange: mov fp,-(sp) ; save frame pointer mov sp,fp clr -(sp) ; alloc stack frame ; mov 4(fp),r4 ; reg <- opd mov (r4),-2(fp) ; ASGNI2 mov @ 6(fp),(r4) ; ASGNI2 mov -2(fp),@ 6(fp) ; ASGNI2 1$: ; mov fp,sp ; pop stack frame mov (sp)+,fp ; restore frame pointer rts pc |
|
/* output unsigned decimal number */ void putu(unsigned n) { unsigned d; if (d = n/10) putu(d); putchar(n%10 + '0'); } |
.GLOBL putu .SBTTL putu putu: mov fp,-(sp) ; save frame pointer mov sp,fp mov r3,-(sp) ; save ; mov 4(fp),r1 ; reg <- opd mov #10,r0 ; reg <- opd jsr pc,$DIVU ; DIVU2 mov r0,r3 ; LOADU2 tst r0 beq 3$ mov r3,-(sp) ; ARGU2 jsr pc,putu add #2,sp ; pop args 3$: mov 4(fp),r1 ; reg <- opd mov #10,r0 ; reg <- opd jsr pc,$DIVU ; MODU2 mov r1,r4 add #48,r4 movb r4,-(sp) ; ARGI2(CVII2) jsr pc,putchar add #2,sp ; pop args 2$: ; mov (sp)+,r3 ; restore mov (sp)+,fp ; restore frame pointer rts pc |
|
void putd(int n) { if (n < 0) { putchar('-'); putu(-n); }else putu(n); } In two places, the compiler is unnecessarily loading n into a register. The ARGI2 rule should directly push 4(FP) and then negate top of stack. However lcc inserts a "LOAD" operator above the operand, which breaks any template we might write to prevent this. |
.GLOBL putd .SBTTL putd putd: mov fp,-(sp) ; save frame pointer mov sp,fp ; tst 4(fp) bpl 6$ mov #45,-(sp) ; ARGI2 jsr pc,putchar add #2,sp ; pop args mov 4(fp),r4 ; reg <- opd neg r4 mov r4,-(sp) ; ARGU2 jsr pc,putu add #2,sp ; pop args br 7$ 6$: mov 4(fp),r4 ; reg <- opd mov r4,-(sp) ; ARGU2 jsr pc,putu add #2,sp ; pop args 7$: 5$: ; mov (sp)+,fp ; restore frame pointer rts pc |
|
/* partition - partition a[i..j] */ int partition(a, i, j) int a[]; { int v, k; j++; k = i; v = a[k]; while (i < j) { do i++; while (a[i] < v); do j--; while (a[j] > v); if (i < j) exchange(&a[i], &a[j]); } exchange(&a[k], &a[j]); return j; } The ARGP2 rules are working well for us here, and the direct CMP of two frame variables is nice to see. |
.GLOBL partition .SBTTL partition partition: mov fp,-(sp) ; save frame pointer mov sp,fp mov r2,-(sp) ; save mov r3,-(sp) ; save ; inc 8(fp) mov 6(fp),r2 ; reg <- opd mov r2,r4 asl r4 add 4(fp),r4 mov (r4),r3 ; reg <- opd br 10$ 9$: 12$: inc 6(fp) 13$: mov 6(fp),r4 ; reg <- opd asl r4 add 4(fp),r4 cmp (r4),r3 blt 12$ 15$: dec 8(fp) 16$: mov 8(fp),r4 ; reg <- opd asl r4 add 4(fp),r4 cmp (r4),r3 bgt 15$ cmp 6(fp),8(fp) bge 18$ mov 4(fp),r4 ; reg <- opd mov 8(fp),r1 ; reg <- opd asl r1 mov r1,-(sp) add r4,(sp) ; ARGP2(ADDP2) mov 6(fp),r1 ; reg <- opd asl r1 mov r1,-(sp) add r4,(sp) ; ARGP2(ADDP2) jsr pc,exchange add #4,sp ; pop args 18$: 10$: cmp 6(fp),8(fp) blt 9$ mov 4(fp),r4 ; reg <- opd mov 8(fp),r1 ; reg <- opd asl r1 mov r1,-(sp) add r4,(sp) ; ARGP2(ADDP2) mov r2,r1 asl r1 mov r1,-(sp) add r4,(sp) ; ARGP2(ADDP2) jsr pc,exchange add #4,sp ; pop args mov 8(fp),r0 ; reg <- opd 8$: ; mov (sp)+,r3 ; restore mov (sp)+,r2 ; restore mov (sp)+,fp ; restore frame pointer rts pc |
|
/* quick - quicksort a[lb..ub] */ void quick(a, lb, ub) int a[]; { int k, partition(); if (lb >= ub) return; k = partition(a, lb, ub); quick(a, lb, k - 1); quick(a, k + 1, ub); } ARGI2 again working well (DEC and INC top of stack). |
.GLOBL quick .SBTTL quick quick: mov fp,-(sp) ; save frame pointer mov sp,fp mov r3,-(sp) ; save ; cmp 6(fp),8(fp) blt 21$ br 20$ 21$: mov 8(fp),-(sp) ; ARGI2 mov 6(fp),-(sp) ; ARGI2 mov 4(fp),-(sp) ; ARGP2 jsr pc,partition add #6,sp ; pop args mov r0,r3 ; LOADI2 mov r3,-(sp) dec (sp) ; ARGI2(SUBI1) mov 6(fp),-(sp) ; ARGI2 mov 4(fp),-(sp) ; ARGP2 jsr pc,quick add #6,sp ; pop args mov 8(fp),-(sp) ; ARGI2 mov r3,-(sp) inc (sp) ; ARGI2(ADDI1) mov 4(fp),-(sp) ; ARGP2 jsr pc,quick add #6,sp ; pop args 20$: ; mov (sp)+,r3 ; restore mov (sp)+,fp ; restore frame pointer rts pc |
|
/* sort - sort a[0..n-1] into increasing order */ void sort(a, n) int a[]; { quick(a, 0, n-1); } |
.GLOBL sort .SBTTL sort sort: mov fp,-(sp) ; save frame pointer mov sp,fp ; mov 6(fp),-(sp) dec (sp) ; ARGI2(SUBI1) clr -(sp) ; ARGI2 mov 4(fp),-(sp) ; ARGP2 jsr pc,quick add #6,sp ; pop args 23$: ; mov (sp)+,fp ; restore frame pointer rts pc |
|
int main() { int i; sort(in, N); for (i = 0; i < N; i++) { putd(in[i]); putchar(' '); } return 0; } |
.GLOBL main .SBTTL main main: mov r3,-(sp) ; save ; mov #10,-(sp) ; ARGI2 mov #in,-(sp) ; ARGP2 jsr pc,sort add #4,sp ; pop args clr r3 25$: mov r3,r4 asl r4 mov in (r4),-(sp) ; ARGI2 jsr pc,putd add #2,sp ; pop args mov #32,-(sp) ; ARGI2 jsr pc,putchar add #2,sp ; pop args 26$: inc r3 cmp r3, #10 blt 25$ clr r0 24$: ; mov (sp)+,r3 ; restore rts pc .END |
Assemble and list, link, and run above code.
.mac/list:tt1: sort .MAIN. MACRO V05.03b 02:04 Table of contents 3- 18 EXCHANGE 3- 35 PUTU 3- 66 PUTD 3- 94 PARTITION 3- 162 QUICK 3- 197 SORT 3- 214 MAIN ...snip... .MAIN. MACRO V05.03b 02:04 Page 3 1 000012 .RADIX 10 2 000005 FP=%5 ; R5 IS FRAME POINTER 3 .ENABL LSB ; FILE-WIDE LOCAL SYMBOLS 4 5 .GLOBL IN 6 000000 IN: 7 000000 000012 .WORD 10 8 000002 000040 .WORD 32 9 000004 177777 .WORD -1 10 000006 001067 .WORD 567 11 000010 000003 .WORD 3 12 000012 000022 .WORD 18 13 000014 000001 .WORD 1 14 000016 177715 .WORD -51 15 000020 001425 .WORD 789 16 000022 000000 .WORD 0 17 .GLOBL EXCHANGE 18 .SBTTL EXCHANGE 19 000024 EXCHANGE: 20 000024 010546 MOV FP,-(SP) ; SAVE FRAME POINTER 21 000026 010605 MOV SP,FP 22 000030 010346 MOV R3,-(SP) ; SAVE 23 ; 24 000032 016504 000004 MOV 4(FP),R4 ; REG <- OPD 25 000036 011403 MOV (R4),R3 ; REG <- OPD 26 000040 017514 000006 MOV @ 6(FP),(R4) ; ASGNI2 27 000044 010375 000006 MOV R3,@ 6(FP) ; ASGNI2 28 000050 1$: 29 ; 30 000050 012603 MOV (SP)+,R3 ; RESTORE 31 000052 012605 MOV (SP)+,FP ; RESTORE FRAME POINTER 32 000054 000207 RTS PC 33 34 .GLOBL PUTU 35 .SBTTL PUTU 36 000056 PUTU: 37 000056 010546 MOV FP,-(SP) ; SAVE FRAME POINTER 38 000060 010605 MOV SP,FP 39 000062 010346 MOV R3,-(SP) ; SAVE 40 ; 41 000064 016501 000004 MOV 4(FP),R1 ; REG <- OPD 42 000070 012700 000012 MOV #10,R0 ; REG <- OPD 43 000074 004767 000000G JSR PC,$DIVU ; DIVU2 44 000100 010003 MOV R0,R3 ; LOADU2 45 000102 005700 TST R0 46 000104 001405 BEQ 3$ 47 000106 010346 MOV R3,-(SP) ; ARGU2 48 000110 004767 177742 JSR PC,PUTU 49 000114 062706 000002 ADD #2,SP ; POP ARGS 50 000120 3$: 51 000120 016501 000004 MOV 4(FP),R1 ; REG <- OPD 52 000124 012700 000012 MOV #10,R0 ; REG <- OPD 53 000130 004767 000000G JSR PC,$DIVU ; MODU2 54 000134 010104 MOV R1,R4 55 000136 062704 000060 ADD #48,R4 56 000142 110446 MOVB R4,-(SP) ; ARGI2(CVII2) 57 000144 004767 000000G JSR PC,PUTCHAR .MAIN. MACRO V05.03b 02:04 Page 3-1 PUTU 58 000150 062706 000002 ADD #2,SP ; POP ARGS 59 000154 2$: 60 ; 61 000154 012603 MOV (SP)+,R3 ; RESTORE 62 000156 012605 MOV (SP)+,FP ; RESTORE FRAME POINTER 63 000160 000207 RTS PC 64 65 .GLOBL PUTD 66 .SBTTL PUTD 67 000162 PUTD: 68 000162 010546 MOV FP,-(SP) ; SAVE FRAME POINTER 69 000164 010605 MOV SP,FP 70 ; 71 000166 005765 000004 TST 4(FP) 72 000172 100017 BPL 6$ 73 000174 012746 000055 MOV #45,-(SP) ; ARGI2 74 000200 004767 000000G JSR PC,PUTCHAR 75 000204 062706 000002 ADD #2,SP ; POP ARGS 76 000210 016504 000004 MOV 4(FP),R4 ; REG <- OPD 77 000214 005404 NEG R4 78 000216 010446 MOV R4,-(SP) ; ARGU2 79 000220 004767 177632 JSR PC,PUTU 80 000224 062706 000002 ADD #2,SP ; POP ARGS 81 000230 000407 BR 7$ 82 000232 6$: 83 000232 016504 000004 MOV 4(FP),R4 ; REG <- OPD 84 000236 010446 MOV R4,-(SP) ; ARGU2 85 000240 004767 177612 JSR PC,PUTU 86 000244 062706 000002 ADD #2,SP ; POP ARGS 87 000250 7$: 88 000250 5$: 89 ; 90 000250 012605 MOV (SP)+,FP ; RESTORE FRAME POINTER 91 000252 000207 RTS PC 92 93 .GLOBL PARTITION 94 .SBTTL PARTITION 95 000254 PARTITION: 96 000254 010546 MOV FP,-(SP) ; SAVE FRAME POINTER 97 000256 010605 MOV SP,FP 98 000260 010246 MOV R2,-(SP) ; SAVE 99 000262 010346 MOV R3,-(SP) ; SAVE 100 ; 101 000264 005265 000010 INC 8(FP) 102 000270 016502 000006 MOV 6(FP),R2 ; REG <- OPD 103 000274 010204 MOV R2,R4 104 000276 006304 ASL R4 105 000300 066504 000004 ADD 4(FP),R4 106 000304 011403 MOV (R4),R3 ; REG <- OPD 107 000306 000446 BR 10$ 108 000310 9$: 109 000310 12$: 110 000310 005265 000006 INC 6(FP) 111 000314 13$: 112 000314 016504 000006 MOV 6(FP),R4 ; REG <- OPD 113 000320 006304 ASL R4 114 000322 066504 000004 ADD 4(FP),R4 .MAIN. MACRO V05.03b 02:04 Page 3-2 PARTITION 115 000326 021403 CMP (R4),R3 116 000330 002767 BLT 12$ 117 000332 15$: 118 000332 005365 000010 DEC 8(FP) 119 000336 16$: 120 000336 016504 000010 MOV 8(FP),R4 ; REG <- OPD 121 000342 006304 ASL R4 122 000344 066504 000004 ADD 4(FP),R4 123 000350 021403 CMP (R4),R3 124 000352 003367 BGT 15$ 125 000354 026565 000006 000010 CMP 6(FP),8(FP) 126 000362 002020 BGE 18$ 127 000364 016504 000004 MOV 4(FP),R4 ; REG <- OPD 128 000370 016501 000010 MOV 8(FP),R1 ; REG <- OPD 129 000374 006301 ASL R1 130 000376 010146 MOV R1,-(SP) 131 000400 060416 ADD R4,(SP) ; ARGP2(ADDP2) 132 000402 016501 000006 MOV 6(FP),R1 ; REG <- OPD 133 000406 006301 ASL R1 134 000410 010146 MOV R1,-(SP) 135 000412 060416 ADD R4,(SP) ; ARGP2(ADDP2) 136 000414 004767 177404 JSR PC,EXCHANGE 137 000420 062706 000004 ADD #4,SP ; POP ARGS 138 000424 18$: 139 000424 10$: 140 000424 026565 000006 000010 CMP 6(FP),8(FP) 141 000432 002726 BLT 9$ 142 000434 016504 000004 MOV 4(FP),R4 ; REG <- OPD 143 000440 016501 000010 MOV 8(FP),R1 ; REG <- OPD 144 000444 006301 ASL R1 145 000446 010146 MOV R1,-(SP) 146 000450 060416 ADD R4,(SP) ; ARGP2(ADDP2) 147 000452 010201 MOV R2,R1 148 000454 006301 ASL R1 149 000456 010146 MOV R1,-(SP) 150 000460 060416 ADD R4,(SP) ; ARGP2(ADDP2) 151 000462 004767 177336 JSR PC,EXCHANGE 152 000466 062706 000004 ADD #4,SP ; POP ARGS 153 000472 016500 000010 MOV 8(FP),R0 ; REG <- OPD 154 000476 8$: 155 ; 156 000476 012603 MOV (SP)+,R3 ; RESTORE 157 000500 012602 MOV (SP)+,R2 ; RESTORE 158 000502 012605 MOV (SP)+,FP ; RESTORE FRAME POINTER 159 000504 000207 RTS PC 160 161 .GLOBL QUICK 162 .SBTTL QUICK 163 000506 QUICK: 164 000506 010546 MOV FP,-(SP) ; SAVE FRAME POINTER 165 000510 010605 MOV SP,FP 166 000512 010346 MOV R3,-(SP) ; SAVE 167 ; 168 000514 026565 000006 000010 CMP 6(FP),8(FP) 169 000522 002401 BLT 21$ 170 000524 000437 BR 20$ 171 000526 21$: .MAIN. MACRO V05.03b 02:04 Page 3-3 QUICK 172 000526 016546 000010 MOV 8(FP),-(SP) ; ARGI2 173 000532 016546 000006 MOV 6(FP),-(SP) ; ARGI2 174 000536 016546 000004 MOV 4(FP),-(SP) ; ARGP2 175 000542 004767 177506 JSR PC,PARTITION 176 000546 062706 000006 ADD #6,SP ; POP ARGS 177 000552 010003 MOV R0,R3 ; LOADI2 178 000554 010346 MOV R3,-(SP) 179 000556 005316 DEC (SP) ; ARGI2(SUBI1) 180 000560 016546 000006 MOV 6(FP),-(SP) ; ARGI2 181 000564 016546 000004 MOV 4(FP),-(SP) ; ARGP2 182 000570 004767 177712 JSR PC,QUICK 183 000574 062706 000006 ADD #6,SP ; POP ARGS 184 000600 016546 000010 MOV 8(FP),-(SP) ; ARGI2 185 000604 010346 MOV R3,-(SP) 186 000606 005216 INC (SP) ; ARGI2(ADDI1) 187 000610 016546 000004 MOV 4(FP),-(SP) ; ARGP2 188 000614 004767 177666 JSR PC,QUICK 189 000620 062706 000006 ADD #6,SP ; POP ARGS 190 000624 20$: 191 ; 192 000624 012603 MOV (SP)+,R3 ; RESTORE 193 000626 012605 MOV (SP)+,FP ; RESTORE FRAME POINTER 194 000630 000207 RTS PC 195 196 .GLOBL SORT 197 .SBTTL SORT 198 000632 SORT: 199 000632 010546 MOV FP,-(SP) ; SAVE FRAME POINTER 200 000634 010605 MOV SP,FP 201 ; 202 000636 016546 000006 MOV 6(FP),-(SP) 203 000642 005316 DEC (SP) ; ARGI2(SUBI1) 204 000644 005046 CLR -(SP) ; ARGI2 205 000646 016546 000004 MOV 4(FP),-(SP) ; ARGP2 206 000652 004767 177630 JSR PC,QUICK 207 000656 062706 000006 ADD #6,SP ; POP ARGS 208 000662 23$: 209 ; 210 000662 012605 MOV (SP)+,FP ; RESTORE FRAME POINTER 211 000664 000207 RTS PC 212 213 .GLOBL MAIN 214 .SBTTL MAIN 215 000666 MAIN: 216 000666 010346 MOV R3,-(SP) ; SAVE 217 ; 218 000670 012746 000012 MOV #10,-(SP) ; ARGI2 219 000674 012746 000000' MOV #IN,-(SP) ; ARGP2 220 000700 004767 177726 JSR PC,SORT 221 000704 062706 000004 ADD #4,SP ; POP ARGS 222 000710 005003 CLR R3 223 000712 25$: 224 000712 010304 MOV R3,R4 225 000714 006304 ASL R4 226 000716 016446 000000' MOV IN (R4),-(SP) ; ARGI2 227 000722 004767 177234 JSR PC,PUTD 228 000726 062706 000002 ADD #2,SP ; POP ARGS .MAIN. MACRO V05.03b 02:04 Page 3-4 MAIN 229 000732 012746 000040 MOV #32,-(SP) ; ARGI2 230 000736 004767 000000G JSR PC,PUTCHAR 231 000742 062706 000002 ADD #2,SP ; POP ARGS 232 000746 26$: 233 000746 005203 INC R3 234 000750 020327 000012 CMP R3, #10 235 000754 002756 BLT 25$ 236 000756 005000 CLR R0 237 000760 24$: 238 ; 239 000760 012603 MOV (SP)+,R3 ; RESTORE 240 000762 000207 RTS PC 241 242 000001 .END .MAIN. MACRO V05.03b 02:04 Page 3-5 Symbol table EXCHAN 000024RG MAIN 000666RG PUTCHA= ****** GX PUTU 000056RG SORT 000632RG FP =%000005 PARTIT 000254RG PUTD 000162RG QUICK 000506RG $DIVU = ****** GX IN 000000RG . ABS. 000000 000 (RW,I,GBL,ABS,OVR) 000764 001 (RW,I,LCL,REL,CON) Errors detected: 0 *** Assembler statistics Work file reads: 0 Work file writes: 0 Size of work file: 9202 Words ( 36 Pages) Size of core pool: 13056 Words ( 51 Pages) Operating system: RT-11 Elapsed time: 00:00:01.28 DK:SORT,TT1:SORT=DK:SORT .link sort,lccrt .sort -51 -1 0 1 3 10 18 32 567 789 .