Hexagon absdif64 4 binsrch 10 bitrev64 1 gcdivis 8 getipstr 7 getmacst 12 getvlq 5 heapSort 18 inssort 9 lcmult 4 nsamebit 4 putipstr 14 putmacst 6 putvlq 9 search64 6 sequence 4 sqroot64 5 ucnvrf 11 udiv128 10 udiv64 9 um64x64 6 --------------- 162 S/390 ID32 VAX WE32K M68K IA-32 ARM ARC PowerPC SPARC MIPS RISC-V Nios2 Xtensa 88K OR1K µBlaze PA-RISC SH-4 CRIS Bfin Hexagon absdif64 13 24 11 21 11 7 6 7 11 8 12 12 12 13 11 14 12 6 18 11 18 6 binsrch 23 22 16 21 22 20 15 15 19 21 18 18 18 17 18 22 19 14 25 27 24 15 bitrev64 16 20 7 17 9 6 4 6 13 15 13 13 15 12 12 16 9 8 9 6 6 2 gcdivis 16 0 11 12 11 11 11 10 15 16 12 13 13 13 14 20 15 13 21 16 18 13 getipstr 15 15 9 16 15 15 11 11 13 14 14 15 14 15 14 15 14 11 17 14 15 13 getmacst 30 32 17 29 28 27 22 22 27 30 25 27 26 28 27 30 27 24 35 30 33 20 getvlq 15 13 8 10 9 11 10 10 12 12 9 11 10 11 11 11 11 8 12 11 11 10 heapSort 52 56 29 48 37 38 35 33 44 48 44 43 44 38 37 52 42 35 56 50 49 33 inssort 17 19 13 20 19 17 15 14 17 20 16 16 16 15 17 21 19 15 21 21 20 14 lcmult 7 24 5 8 9 12 5 5 6 5 6 5 5 5 5 5 5 19 18 29 14 9 nsamebit 12 14 10 11 15 6 8 8 8 11 9 10 9 11 9 11 10 9 12 13 12 6 putipstr 30 27 15 25 24 25 23 19 26 29 26 24 26 24 27 30 26 24 42 31 35 24 putmacst 24 27 12 23 18 20 16 17 19 23 20 22 22 21 20 25 22 16 29 23 23 14 putvlq 20 20 14 17 13 15 12 12 15 19 15 16 16 16 15 19 16 13 21 18 18 13 search64 14 15 12 17 17 14 12 9 14 15 12 13 12 12 14 16 14 10 13 17 16 10 sequence 9 12 7 13 8 10 7 6 10 12 10 10 10 9 10 12 11 13 13 10 10 6 sqroot64 12 18 10 18 14 12 10 10 11 12 15 16 16 16 13 14 11 9 14 15 19 8 ucnvrf 24 20 12 20 18 18 16 13 22 24 20 18 20 18 23 22 22 18 32 19 26 16 udiv128 22 49 19 41 24 27 22 17 24 28 34 31 36 32 22 30 27 22 30 31 33 13 udiv64 4 27 13 26 5 4 13 11 16 9 20 19 20 18 16 19 15 13 14 18 13 17 um64x64 21 54 31 35 16 30 12 11 15 17 25 21 21 27 60 46 15 30 23 22 24 15 ---------------------------------------------------------------------------------------------------------------------------------------------- 396 508 281 448 342 345 285 266 357 388 375 373 381 371 395 450 362 330 475 432 437 277 S/390 ID32 VAX WE32K M68K IA-32 ARM ARC PowerPC SPARC MIPS RISC-V Nios2 Xtensa 88K OR1K µBlaze PA-RISC SH-4 CRIS Bfin Hexagon absdif64 36 66 36 56 32 14 24 24 44 32 80 38 48 36 44 56 48 24 36 22 36 24 binsrch 80 62 68 72 54 37 60 50 76 84 96 56 72 41 72 88 76 56 50 56 48 56 bitrev64 48 62 28 68 24 14 16 22 52 60 64 36 60 36 48 64 36 32 18 12 20 8 getipstr 48 38 40 52 38 25 44 36 52 56 64 40 56 38 56 60 56 48 34 32 32 44 getmacst 100 96 72 96 80 51 88 70 108 120 128 74 104 74 108 120 108 96 70 72 72 76 getvlq 52 38 32 32 28 21 40 26 48 48 48 28 40 27 44 44 44 32 24 28 24 32 heapSort 172 172 100 156 110 85 140 110 176 192 224 134 176 107 148 208 168 144 112 108 104 116 inssort 60 66 56 64 56 35 60 40 68 80 96 48 64 36 68 84 76 64 42 44 40 48 lcmult 64 58 47 72 52 41 64 46 84 84 112 48 72 49 76 100 80 128 78 98 70 84 nsamebit 32 38 32 36 42 13 32 20 32 44 48 26 36 29 36 44 40 40 24 28 28 24 putipstr 116 84 88 100 76 50 96 74 104 120 144 80 108 68 108 120 108 96 92 88 84 104 putmacst 88 82 44 80 56 41 68 60 76 92 96 62 88 56 80 100 88 64 58 48 56 56 putvlq 64 54 56 56 36 31 48 40 60 76 80 42 64 44 60 76 64 56 42 44 40 48 search64 48 42 44 52 48 31 48 26 56 60 64 38 48 28 56 64 56 40 26 36 32 44 sequence 32 28 24 36 22 17 28 18 40 48 48 24 40 20 40 48 44 56 26 20 24 24 sqroot64 36 42 36 52 40 27 40 32 44 48 80 42 60 42 52 56 44 40 28 32 44 32 ucnvrf 88 58 56 78 66 44 72 58 96 110 128 72 96 55 98 94 96 160 80 60 80 78 udiv128 80 140 64 148 66 75 88 64 96 112 176 100 144 88 88 120 108 88 60 64 88 56 udiv64 12 72 40 84 22 9 52 36 64 36 96 48 80 51 64 76 60 56 32 40 36 68 um64x64 64 136 116 128 44 47 48 42 60 68 112 70 84 71 240 184 60 120 46 44 64 52 ---------------------------------------------------------------------------------------------------------------------------------------------- 1320 1434 1069 1518 992 708 1156 894 1436 1570 1984 1106 1540 996 1586 1806 1460 1440 978 976 1022 1074 S/390 GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 41200001 LA 2,1 # Файлов дескриптор 1: stdout (стандартен изход) 5 0004 C0300000 0000 LARL 3,MSG # Адрес на низа 6 000a 4140001B LA 4,LEN # Дължина на низа (UTF-8) 7 000e 0A04 SVC 4 # SYS_write (запис: /usr/include/{архит.}/asm/unistd.h 8 0010 0A01 SVC 1 # SYS_exit (завършване на процеса) 9 0012 0707 .data 10 0000 D097D0B4 D180D0B0 MSG: .ascii "Здравей, свят!\n\n" 10 D0B2D0B5 D0B92C20 10 D181D0B2 D18FD182 10 210A0A 11 001b 00 LEN = . - MSG ==> id32/hello.s <== 00000d 2401 1 lis 0,1 File descriptor 1 (stdout) 00002d E1E0 0004 2 svc 14,4 write (see /usr/include/sys.s) 00006d 0000 0012 3 dc MSG String address 0000Ad 0000 0021 4 dc LEN String length 0000Ed E1E0 0001 5 svc 14,1 exit 00012d 4865 6C6C 6F2C 2077 6 MSG db c'Hello, world!',x'0a',x'0a' 6F72 6C64 210A 0A 6 00000021d 7 LEN equ * - MSG VAX GAS hello.s page 1 1 .globl _start 2 _start: 3 0000 0000 .word 0 # Входна маска (gas няма директива .entry) 4 0002 DD8F1B00 0000 PUSHL $LEN # Дължина на низа (UTF-8) 5 0008 DFEF1200 0000 PUSHAL MSG # Адрес на низа 6 000e DD01 PUSHL $1 # Файлов дескриптор 1: stdout (стандартен изход) 7 0010 DD03 PUSHL $3 # Брой аргументи 8 0012 D05E5C MOVL SP,AP # Направи SP указател към аргументите 9 0015 BC04 CHMK $4 # SYS_write (запис: /usr/sys/h/syscall.h) 10 0017 DD00 PUSHL $0 11 0019 D05E5C MOVL SP,AP 12 001c BC01 CHMK $1 # SYS_exit (завършване на процеса) 13 001e 0101 .data 14 0020 D097D0B4 D180D0B0 D0B2D0B5 MSG: .ascii "Здравей, свят!\n\n" 14 D0B92C20 D181D0B2 D18FD182 14 210A0A 15 003b 00 LEN = . - MSG ==> we32k/hello.s <== .globl _start section .text .globl main _start() _start: # Entry point main() main: # sdb breakpoint 0: 84 4c 4a MOVW %sp,%ap 3: a0 01 PUSHW &1 # File descriptor 1: stdout (standard output) 5: a0 4f 24 00 00 00 PUSHW &MSG # String address b: a0 4f 0f 00 00 00 PUSHW &LEN # String length 11: 84 04 40 MOVW &4,%r0 # write() - see /usr/src/lib/libc/m32/sys/write.s 14: 84 20 41 MOVW &4*8,%r1 17: 30 61 GATE 19: 84 04 40 MOVW &4,%r0 # exit() - see /usr/src/lib/libc/m32/sys/exit.s 1c: 84 08 41 MOVW &1*8,%r1 1f: 30 61 GATE 21: 70 NOP 22: 70 NOP 23: 70 NOP .data MSG: .byte 72,101,108,108,111,44,32,119,111,114,108,100,33,10,10 .set LEN, . - MSG 68K GAS hello.s page 1 1 .global _start,main 2 _start: | Входна точка 3 main: | Точка на прекъсване на gdb 4 0000 7004 MOVEL #4,%D0 | SYS_write (запис: /usr/include/sys/syscall.h) 5 0002 7201 MOVEL #1,%D1 | Файлов дескриптор 1: stdout (стандартен изход 6 0004 243C 0000 0000 MOVEL #MSG,%D2 | Адрес на низа 7 000a 263C 0000 001B MOVEL #LEN,%D3 | Дължина на низа (UTF-8) 8 0010 4E40 TRAP #0 | Извикай съответната функция на ядрото на ОС 9 0012 7001 MOVEL #1,%D0 | SYS_exit (завършване на процеса) 10 0014 4E40 TRAP #0 11 .data 12 0000 D097 D0B4 D180 MSG: .ascii "Здравей, свят!\n\n" 12 D0B0 D0B2 D0B5 12 D0B9 2C20 D181 12 D0B2 D18F D182 12 210A 0A 13 LEN = . - MSG x86 GAS hello386.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 B8040000 00 MOV $4,%EAX # SYS_write (запис: /usr/include/{архит.}/asm/unistd.h 5 0005 BB010000 00 MOV $1,%EBX # Файлов дескриптор 1: stdout (стандартен изход) 6 000a B9000000 00 MOV $MSG,%ECX# Адрес на низа 7 000f BA1B0000 00 MOV $LEN,%EDX# Дължина на низа (UTF-8) 8 0014 CD80 INT $0x80 # Извикай съответната функция на ядрото на ОС 9 0016 B8010000 00 MOV $1,%EAX # SYS_exit (завършване на процеса) 10 001b CD80 INT $0x80 11 .data 12 0000 D097D0B4 D180D0B0 MSG: .ascii "Здравей, свят!\n\n" 12 D0B2D0B5 D0B92C20 12 D181D0B2 D18FD182 12 210A0A 13 LEN = . - MSG ARM GAS hello.s page 1 1 .global _start,main 2 _start: // Входна точка 3 main: // Точка на прекъсване на gdb 4 0000 0470A0E3 MOV R7,#4 // SYS_write (запис: /usr/include/{архит.}/asm/unistd.h 5 0004 0100A0E3 MOV R0,#1 // Файлов дескриптор 1: stdout (стандартен изход) 6 0008 0C109FE5 LDR R1,=MSG // Адрес на низа 7 000c 1B20A0E3 MOV R2,#LEN // Дължина на низа (UTF-8) 8 0010 000000EF SWI 0 // Извикай съответната функция на ядрото на ОС 9 0014 0170A0E3 MOV R7,#1 // SYS_exit (завършване на процеса) 10 0018 000000EF SWI 0 11 .data 12 0000 D097D0B4 MSG: .ascii "Здравей, свят!\n\n" 12 D180D0B0 12 D0B2D0B5 12 D0B92C20 12 D181D0B2 13 LEN = . - MSG ARC GAS hello.s page 1 1 .global __start,main 2 __start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 8A20 0110 MOV r8,64 # SYS_write (запис: /usr/include/{архит.}/asm/unistd.h 5 0004 4A20 4000 MOV r0,1 # Файлов дескриптор 1: stdout (стандартен изход) 6 0008 0A21 800F 0000 0000 MOV r1,MSG # Адрес на низа 7 0010 0A22 800F 0000 1B00 MOV r2,LEN # Дължина на низа (UTF-8) 8 0018 1E78 TRAP_S 0 # Извикай съответната функция на ядрото на ОС 9 001a 8A20 4117 MOV r8,93 # SYS_exit (завършване на процеса) 10 001e 1E78 TRAP_S 0 11 .data 12 0000 D097 D0B4 D180 D0B0 MSG: .ascii "Здравей, свят!\n\n" 12 D0B2 D0B5 D0B9 2C20 12 D181 D0B2 D18F D182 12 210A 0A 13 LEN = . - MSG PPC GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 38000004 li r0,4 # SYS_write (запис: /usr/include/sys/syscall.h) 5 0004 38600001 li r3,1 # Файлов дескриптор 1: stdout (стандартен изход 6 0008 3C800000 lis r4,(MSG)@ha # Зареди старшата част на адреса на низа, << 16 7 000c 38840000 addi r4,r4,(MSG)@l # Добави младшата (lis..ha добавя 1, ако е отр. 8 0010 38A0001B li r5,27 # Дължина на низа (UTF-8) 9 0014 44000002 sc # Извикай съответната функция на ядрото на ОС 10 0018 60000000 nop # Ще бъде прескочена при успешен SC (SysCall) 11 001c 38000001 li r0,1 # SYS_exit (завършване на процеса) 12 0020 44000002 sc 13 .data 14 0000 D097D0B4 MSG: .ascii "Здравей, свят!\n\n" 14 D180D0B0 14 D0B2D0B5 14 D0B92C20 14 D181D0B2 SPARC GAS hello.s page 1 1 .global _start,main 2 _start: ! Входна точка 3 main: ! Точка на прекъсване на gdb 4 0000 90102001 mov 1,%o0 ! Файлов дескриптор 1: stdout (стандартен изход) 5 0004 13000000 set MSG,%o1 ! Адрес на низа 5 92126000 6 000c 9410201B mov LEN,%o2 ! Дължина на низа (UTF-8) 7 0010 82102004 mov 4,%g1 ! SYS_write (запис: /usr/include/sys/syscall.h) 8 0014 91D02008 ta 8 ! Извикай съответната функция на ядрото на ОС 9 0018 82102001 mov 1,%g1 ! SYS_exit (завършване на процеса) 10 001c 91D02008 ta 8 11 .align 4 12 .data 13 0000 D097D0B4 MSG: .ascii "Здравей, свят!\n\n" 13 D180D0B0 13 D0B2D0B5 13 D0B92C20 13 D181D0B2 14 LEN = . - MSG MIPS GAS hello.s page 1 1 .ent main 2 .global __start,main 3 __start: # Входна точка 4 main: # Точка на прекъсване на gdb 5 0000 24040001 LI $4,1 # Файлов дескриптор 1: stdout (стандартен изход) 6 0004 3C050000 24A50000 LA $5,MSG # Адрес на низа 7 000c 2406001B LI $6,LEN # Дължина на низа (UTF-8) 8 0010 24020FA4 LI $2,4004 # SYS_write (запис: /usr/include/{архит.}/asm/unistd.h) 9 0014 0000000C SYSCALL # Извикай съответната функция на ядрото на ОС 10 0018 24020FA1 LI $2,4001 # SYS_exit (завършване на процеса) 11 001c 0000000C SYSCALL 12 .end main 13 .data 14 0000 D097D0B4 D180D0B0 D0B2D0B5 MSG: .ascii "Здравей, свят!\n\n" 14 D0B92C20 D181D0B2 D18FD182 14 210A0A 15 001b 00000000 00 LEN = . - MSG RISC-V GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 0545 LI a0,1 # Файлов дескриптор 1: stdout (стандартен изход) 5 0002 97050000 93850500 LA a1,MSG # Адрес на низа 6 000a 6D46 LI a2,27 # Дължина на низа (UTF-8) 7 000c 93080004 LI a7,64 # SYS_write (запис: /usr/include/{архит.}/asm/unistd.h) 8 0010 73000000 ECALL # Извикай съответната функция на ядрото на ОС 9 0014 9308D005 LI a7,93 # SYS_exit (завършване на процеса) 10 0018 73000000 ECALL 11 001c D097D0B4 D180D0B0 MSG: .ascii "Здравей, свят!\n\n" 11 D0B2D0B5 D0B92C20 11 D181D0B2 D18FD182 11 210A0A00 Nios II GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 14108000 MOVUI r2,64 # SYS_write (запис: …/include/арх./asm/unistd.h 5 0004 54000001 MOVUI r4,1 # Файлов дескриптор 1: stdout (стандартен изход 6 0008 34004001 04004029 MOVIA r5,MSG # Зареди адреса на низа 7 0010 D4068001 MOVUI r6,LEN # Дължина на низа (UTF-8) 8 0014 3A683B00 TRAP # Извикай съответната функция на ядрото на ОС 9 0018 54178000 MOVUI r2,93 # SYS_exit (завършване на процеса) 10 001c 3A683B00 TRAP 11 .data 12 0000 D097D0B4 D180D0B0 MSG: .ascii "Здравей, свят!\n\n" 12 D0B2D0B5 D0B92C20 12 D181D0B2 D18FD182 12 210A0A 13 LEN = . - MSG Xtensa GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 0CD2 MOVI a2,13 # SYS_write (запис: …/include/арх./asm/unistd.h 5 0002 0C16 MOVI a6,1 # Файлов дескриптор 1: stdout (стандартен изход 6 0004 310000 MOVI a3,MSG # Зареди адреса на низа 7 0007 410000 MOVI a4,LEN # Дължина на низа (UTF-8) 8 000a 005000 SYSCALL # Извикай съответната функция на ядрото на ОС 9 000d 22A076 MOVI a2,118 # SYS_exit (завършване на процеса) 10 0010 005000 SYSCALL 11 .data 12 0000 D097D0B4 D180D0B0 MSG: .ascii "Здравей, свят!\n\n" 12 D0B2D0B5 D0B92C20 12 D181D0B2 D18FD182 12 210A0A 13 LEN = . - MSG 88K GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 0000 155F0020 main: # Точка на прекъсване на gdb 4 0004 157F0024 ld r10,sp,32# Вж „m88100_syscall()“ в „trap.c,v 1.33“, OpenBSD 4.0 5 0008 159F0028 ld r11,sp,36 6 000c 58400001 ld r12,sp,40 7 0010 5C800000 or r2,r0,1 # Файлов дескриптор 1: stdout (стандартен изход) 8 0014 58640030 or.u r4,r0,hi16(MSG)# Зареди старшата част на адреса на низа, << 16 9 0018 5880001B or r3,r4,lo16(MSG)# Добави младшата му част 10 001c 59A00004 or r4,r0,LEN# Дължина на низа (UTF-8) 11 0020 F000D080 or r13,r0,4 # SYS_write (запис: /usr/include/sys/syscall.h) 12 0024 58000000 tb0 0,r0,128 # Извикай съответната функция на ядрото на ОС 13 0028 59A00001 or r0,r0,0 # Ще бъде прескочена при успешен „tb0“ 14 002c F000D080 or r13,r0,1 # SYS_exit (завършване на процеса) 15 0030 D097D0B4 tb0 0,r0,128 15 D180D0B0 15 D0B2D0B5 15 D0B92C20 15 D181D0B2 16 004b 00000000 MSG: .ascii "Здравей, свят!\n\n" 16 00 LEN = . - MSG UNDEFINED SYMBOLS LEN Or1k GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 A9600040 L.ORI R11,R0,64 # SYS_write (запис: …/include/арх./asm/unistd.h 5 0004 A8600001 L.ORI R3,R0,1 # Файлов дескриптор 1: stdout (стандартен изход 6 0008 18800000 L.MOVHI R4,HI(MSG) # Зареди старшата част на адреса на низа, << 16 7 000c A8840000 L.ORI R4,R4,LO(MSG) # Добави младшата 8 0010 A8A0001B L.ORI R5,R0,LEN # Дължина на низа (UTF-8) 9 0014 20000001 L.SYS 1 # Извикай съответната функция на ядрото на ОС 10 0018 A960005D L.ORI R11,R0,93 # SYS_exit (завършване на процеса) 11 001c 20000001 L.SYS 1 12 .data 13 0000 D097D0B4 MSG: .ascii "Здравей, свят!\n\n" 13 D180D0B0 13 D0B2D0B5 13 D0B92C20 13 D181D0B2 14 LEN = . - MSG Xilinx MicroBlaze GAS hello.s page 1 1 .global _start,main 2 _start: # Входна точка 3 main: # Точка на прекъсване на gdb 4 0000 040080A1 ORI R12,R0,4 # SYS_write (запис: …/include/арх./asm/unistd.h 5 0004 0100A0A0 ORI R5,R0,1 # Файлов дескриптор 1: stdout (стандартен изход 6 0008 000000B0 0000C0A0 ORI R6,R0,MSG # Зареди адреса на низа 7 0010 000000B0 1B00E0A0 ORI R7,R0,LEN # Дължина на низа (UTF-8) 8 0018 0800CCB9 BRKI R14,8 # Извикай съответната функция на ядрото на ОС 9 001c 010080A1 ORI R12,R0,1 # SYS_exit (завършване на процеса) 10 0020 0800CCB9 BRKI R14,8 11 .data 12 0000 D097D0B4 D180D0B0 MSG: .ascii "Здравей, свят!\n\n" 12 D0B2D0B5 D0B92C20 12 D181D0B2 D18FD182 12 210A0A 13 LEN = . - MSG HP92453-03 UX.11.01.17 PA-RISC 2.0 Assembler Sep 12 2001 Copyright Hewlett Packard 1985,1993 1 .code -> .SPACE $TEXT$,SORT=8 -> .SUBSPA $CODE$,QUAD=0,ALIGN=0x8,ACCESS=0x2c,SORT=24,CODE_ONLY 2 .export $START$ 3 $START$ ; Входна точка 4 00000000 (22400801) LDIL 0x180000,%r18 ; 0x180000 << 11 = 0xC0000000, база на спод.об. 5 00000004 (34160008) LDI 4,%r22 ; SYS_write (/usr/include/sys/scall_define.h) 6 00000008 (341A0002) LDI 1,%r26 ; Файлов дескриптор 1: stdout (стандартен изход 7 0000000C (23200000)* LDIL L%MSG,%r25 ; Зареди старшата част на адреса на низа, << 11 8 00000010 (37390000)* LDO R%MSG(%r25),%r25; Добави младшите му 11 бита като отместване 9 00000014 (E640E008) BE,L 4(%sr7,%r18) ; Извикай функцията на ядрото на ОС (отложено) 10 00000018 (34180036) LDI 27,%r24 ; Дължина на низа (изпълнява се преди BE,L!) 11 0000001C (E240E008) BE 4(%sr7,%r18) 12 00000020 (34160002) LDI 1,%r22 ; SYS_exit (завършване; изпълнява се преди BE) 13 .data -> .SPACE $PRIVATE$,SPNUM=1,PRIVATE,SORT=16 -> .SUBSPA $DATA$,QUAD=0x1,ALIGN=0x8,ACCESS=0x1f,SORT=16 14 40000000 (D097D0B4) MSG .string "Здравей, свят!\n\n" 15 16 .subspa $UNWIND_END$,access=0x1F 17 .export $UNWIND_END 18 $UNWIND_END Renesas / SuperH SH GAS Little Endian hello.s page 1 1 .global _start,main 2 _start: ! Входна точка 3 main: ! Точка на прекъсване на gdb 4 0000 04E3 MOV #4,R3 ! SYS_write (запис: /usr/include/sys/syscall.h) 5 0002 01E4 MOV #1,R4 ! Файлов дескриптор 1: stdout (стандартен изход 6 0004 09D5 MOV.L MPTR,R5 ! Адрес на низа 7 0006 1BE6 MOV #LEN,R6 ! Дължина на низа (UTF-8) 8 0008 17C3 TRAPA #0x17 ! Извикай съответната функция на ядрото на ОС 9 000a 01E3 MOV #1,R3 ! SYS_exit (завършване на процеса) 10 000c 17C3 TRAPA #0x17 11 000e D097D0B4 MSG: .ascii "Здравей, свят!\n\n" 11 D180D0B0 11 D0B2D0B5 11 D0B92C20 11 D181D0B2 12 LEN = . - MSG 13 0029 000900 .align 2 14 002c 0E000000 MPTR: .long MSG GAS for CRIS hello.s page 1 1 .global _start,main 2 _start: ; Входна точка 3 main: ; Точка на прекъсване на gdb 4 0000 4492 MOVEQ 4,R9 ; SYS_write (запис: /usr/include/{архит.}/asm/unistd.h) 5 0002 41A2 MOVEQ 1,R10 ; Файлов дескриптор 1: stdout (стандартен изход) 6 0004 6FBE0000 0000 MOVE.D MSG,R11 ; Адрес на низа 7 000a 5BC2 MOVEQ LEN,R12 ; Дължина на низа (UTF-8) 8 000c 3DE9 BREAK 13 ; Извикай съответната функция на ядрото на ОС 9 000e 4192 MOVEQ 1,R9 ; SYS_exit (завършване на процеса) 10 0010 3DE9 BREAK 13 11 0012 D097D0B4 D180D0B0 MSG: .ascii "Здравей, свят!\n\n" 11 D0B2D0B5 D0B92C20 11 D181D0B2 D18FD182 11 210A0A 12 002d 000000 LEN = . - MSG BFIN GAS hello.s page 1 1 .global __start,_main 2 __start: # Входна точка 3 _main: # Точка на прекъсване на gdb 4 0000 2068 P0 = 4; # SYS_write (запис: /usr/include/{архит.}/asm/unistd.h) 5 0002 0860 R0 = 1; # Файлов дескриптор 1: stdout (стандартен изход) 6 0004 41E10000 R1.H = MSG; # Адрес на низа 7 0008 01E10000 R1.L = MSG; 8 000c 22E11B00 R2 = LEN; # Дължина на низа (UTF-8) 9 0010 A000 EXCPT 0; # Извикай съответната функция на ядрото на ОС 10 0012 0868 P0 = 1; # SYS_exit (завършване на процеса) 11 0014 A000 EXCPT 0; 12 0016 0000 .data 13 0000 D097D0B4 MSG: .ascii "Здравей, свят!\n\n" 13 D180D0B0 13 D0B2D0B5 13 D0B92C20 13 D181D0B2 14 001b 00 .equ LEN, . - MSG Hexagon GAS hello.s page 1 1 .global _start,main 2 _start: // Входна точка 3 main: // Точка на прекъсване на gdb 4 { R6 = #64 // SYS_write (запис: /usr/include/{архит.}/asm/unistd.h 5 0000 06480078 20C00078 R0 = #1 } // Файлов дескриптор 1: stdout (стандартен изход) 6 { R1 = #MSG // Адрес на низа 7 0008 00400000 01400078 00400000 02C00078 R2 = #LEN }// Дължина на низа (UTF-8) 8 0018 04C00054 TRAP0 (#1) // Извикай съответната функция на ядрото на ОС 9 001C A6CB0078 R6 = #93 // SYS_exit (завършване на процеса) 10 0020 04C00054 TRAP0 (#1) 11 .data 12 0000 D097D0B4 D180D0B0 D0B2D0B5 D0B92C20 MSG: .ascii "Здравей, свят!\n\n" 12 D181D0B2 D18FD182 210A0A 13 .set LEN, . - MSG S/390 GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри 5:4 (Y1:Y0) и 3:2 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в регистри 5:4:3:2 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 906DF010 STM 6,13,16(15) # Съхрани използваните регистри (LNUX-1007-02) 8 0004 1872 LR 7,2 # Z0 9 0006 1893 LR 9,3 # Z1 10 0008 18D4 LR 13,4 # Y0 11 000a 18B5 LR 11,5 # Y1 12 000c B9960065 MLR 6,5 # 6:7 = Z0 * Y1 13 0010 B99600C2 MLR 12,2 # 12:13 = C:D = Z0 * Y0 14 0014 B9960084 MLR 8,4 # 8:9 = Z1 * Y0 15 0018 B99600A3 MLR 10,3 # 10:11 = Z1 * Y1 16 001c 1B55 SR 5,5 17 001e 1EC7 ALR 12,7 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 18 0020 B9980068 ALCR 6,8 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 19 0024 B99800A5 ALCR 10,5 # A = ст.д.(Z1 * Y1) 20 0028 1EC9 ALR 12,9 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 21 002a B998006B ALCR 6,11 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 22 002e B998005A ALCR 5,10 # A 23 0032 1846 LR 4,6 # B 24 0034 183C LR 3,12 # C 25 0036 182D LR 2,13 # D 26 0038 986DF010 LM 6,13,16(15) # Възстанови съхранените регистри 27 003c 07FE0707 BR 14 # Върни управлението ==> id32/um64x64.s <== 1 * Multiply the 64-bit unsigned numbers in *7(0) (Y1:Y0) and *7(4) (Z1:Z0) and 2 * return the 128-bit result A:B:C:D in *7(0). Register 7 is the stack pointer. 3 * Algorithm: Peter Norton, "Advanced Assembly Language", 1991, pp. 229-230. 4 * 5 * The ID32 lacks unsigned multiplication so we convert the signed one by adding 6 * for each negative factor its "sibling" - the other factor - to the high word. 7 * (H. Warren, Hacker's Delight, 8-3 High-Order Product Signed from/to Unsigned) 8 * 9 * The ID32 lacks "add with carry" instructions as well, so the subroutine can't 10 * be linear anyway, and this frees us to use branches for this conversion too. 11 12 entry um64x64 00000000d 13 um64x64 equ * 00000d 5867 0000 14 l 6,0(7) &Y (reg. 0 can't be index - 29-405R00, p. 1-6, 00004d 5817 0004 15 l 1,4(7) &Z 29-428R06, p. 1-7) 00008d CB70 0020 16 shi 7,32(0) Allocate stack space (8 * 4 bytes = 32 bytes) 0000Cd D087 0000 17 stm 8,0(7) Save reg. 8-15 (used by the calling function) 00010d 58C6 0000 18 l 12,0(6) Y1 00014d 58D6 0004 19 l 13,4(6) Y0 00018d 58E1 0000 20 l 14,0(1) Z1 0001Cd 58F1 0004 21 l 15,4(1) Z0 00020d 083F 22 lr 3,15 Z0 00022d 1C2C 23 mr 2,12 Reg. 2:3 = Z0 * Y1 (as signed numbers) 00024d 08BE 24 lr 11,14 Z1 00026d 1CAC 25 mr 10,12 Reg. 10:11 = Z1 * Y1 ( " " " ") 00028d 085E 26 lr 5,14 Z1 0002Ad 1C4D 27 mr 4,13 Reg. 4:5 = Z1 * Y0 (as signed numbers) 0002Cd 089F 28 lr 9,15 Z0 0002Ed 1C8D 29 mr 8,13 Reg. 8:9 = C:D = Z0 * Y0 ( " " ") 00030d 0700 30 xr 0,0 Clear all bits 00032d 090F 31 cr 0,15 Is Z0 negative? 00034d 2323 0000003Ad 32 bnps L1 No, skip the addings 00036d 0A8D 33 ar 8,13 Yes, add the other factor (Y0) to High(Z0 * Y0) 00038d 0A2C 34 ar 2,12 " " " " " " " (Y1) " " (Z0 * Y1) 0003Ad 090C 35 L1 cr 0,12 Is Y1 negative? 0003Cd 2323 00000042d 36 bnps L2 No, skip the addings 0003Ed 0A2F 37 ar 2,15 Yes, add the other " " (Z0) " " " " 00040d 0AAE 38 ar 10,14 " " " " " " " (Z1) " " (Z1 * Y1) 00042d 090E 39 L2 cr 0,14 Is Z1 negative? 00044d 2323 0000004Ad 40 bnps L3 No, skip the addings 00046d 0AAC 41 ar 10,12 Yes, add the other " " (Y1) " " " " 00048d 0A4D 42 ar 4,13 " " " " " " " (Y0) " " (Z1 * Y0) 0004Ad 090D 43 L3 cr 0,13 Is Y0 negative? 0004Cd 2323 00000052d 44 bnps L4 No, skip the addings 0004Ed 0A4E 45 ar 4,14 Yes, add the other " " (Z1) " " " " 00050d 0A8F 46 ar 8,15 " " " " " " " (Z0) " " (Z0 * Y0) 00052d 0A83 47 L4 ar 8,3 C = High(Z0 * Y0) + Low(Z0 * Y1) 00054d 2382 00000058d 48 bncs L5 00056d 2621 49 ais 2,1 No carry (FFFFFFFF squared = FFFFFFFE00000001) 00058d 0A24 50 L5 ar 2,4 B = High(Z0 * Y1) + High(Z1 * Y0) 0005Ad 2382 0000005Ed 51 bncs L6 0005Cd 26A1 52 ais 10,1 A = High(Z1 * Y1) 0005Ed 0A85 53 L6 ar 8,5 C = High(Z0 * Y0) + Low(Z0 * Y1) + Low(Z1 * Y0) 00060d 2384 00000068d 54 bncs L7 00062d 2621 55 ais 2,1 Process carry 00064d 2382 00000068d 56 bncs L7 (here we can have one) 00066d 26A1 57 ais 10,1 00068d 0A2B 58 L7 ar 2,11 B = High(Z0 * Y1) + Hi (Z1 * Y0) + Low(Z1 * Y1) 0006Ad 2382 0000006Ed 59 bncs L8 0006Cd 26A1 60 ais 10,1 0006Ed 50A6 0000 61 L8 st 10,0(6) A, 00072d 5026 0004 62 st 2,4(6) B, 00076d 5081 0000 63 st 8,0(1) C, 0007Ad 5091 0004 64 st 9,4(1) D. Y and Z are now replaced with result A:B:C:D 0007Ed D187 0000 65 lm 8,0(7) Restore the saved registers 8-15 00082d CA70 0020 66 ahi 7,32(0) Deallocate the stack space (reg.0: no indexing) 00086d 030F 67 br 15 Return to the calling function VAX GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри R3:R2 (Y1:Y0) и R1:R0 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. R3:R2:R1:R0 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 # 5 # Във VAX няма команда за дълго беззнаково умножение, а само за знаково – EMUL. 6 # Превръщаме го в беззнаково, добавяйки към старшите 32 бита на произведението 7 # множителите, като всеки от тях е умножен по знака на другия множител. Сиреч, 8 # за всеки отрицателен множител се добавя неговият „събрат“ – другият множител. 9 # [Това действие е обратното на процедурата, която е описана в статията „Signed 10 # multiplication technique by means of unsigned multiply instruction“, S. Grys, 11 # „Computers and Electrical Engineering 37 (2011)“, стр. 1218] 12 13 .global _um64x64 14 _um64x64: 15 0000 F00F .word 0xFF0 # Съхрани R4-R11 16 0002 7A505300 56 EMUL R0,R3,$0,R6 #---> R7:R6 = Z0 * Y1 (като числа със знак) 17 0007 7A515300 5A EMUL R1,R3,$0,R10#---> R11:R10 = Z1 * Y1 (като числа със знак) 18 000c EF1F0150 54 EXTZV $31,$1,R0,R4# R4 = знакът на множителя в R0 19 0011 EF1F0153 55 EXTZV $31,$1,R3,R5# R5 = " " " " " R3 20 0016 C5535458 MULL3 R3,R4,R8 # R8 = множителят в R3 × знака на множителя в R0 21 001a C5505559 MULL3 R0,R5,R9 # R9 = " " " R0 " " " " " " R3 22 001e C05857 ADDL2 R8,R7 # Преобразувай първото произведение в беззнаково 23 0021 C05957 ADDL2 R9,R7 24 0024 EF1F0151 59 EXTZV $31,$1,R1,R9# R9 = знакът на множителя в R1 25 0029 C5515558 MULL3 R1,R5,R8 # R8 = множителят в R1 × знака на множителя в R3 26 002d C5535955 MULL3 R3,R9,R5 # R5 = " " " R3 " " " " " " R1 27 0031 C0585B ADDL2 R8,R11 # Преобразувай второто произведение в беззнаково 28 0034 C1555B53 ADDL3 R5,R11,R3 #---> R3:R10 = Z1 * Y1 (и довърши преобразуването) 29 0038 EF1F0152 55 EXTZV $31,$1,R2,R5# R5 = знакът на множителя в R2 30 003d C552595B MULL3 R2,R9,R11 # R11 = множителят в R2 × знака на множителя в R1 31 0041 7A515200 58 EMUL R1,R2,$0,R8 #---> R9:R8 = Z1 * Y0 (като числа със знак) 32 0046 C45551 MULL2 R5,R1 # R1 = множителят в R1 × знака на множителя в R2 33 0049 C05159 ADDL2 R1,R9 # Преобразувай третото произведение в беззнаково 34 004c C45254 MULL2 R2,R4 # R4 = множителят в R2 × знака на множителя в R0 35 004f C45055 MULL2 R0,R5 # R5 = " " " R0 " " " " " " R2 36 0052 7A525000 50 EMUL R2,R0,$0,R0 #---> R1:R0 = C:D = Z0 * Y0 (като числа със знак) 37 0057 C15B5952 ADDL3 R11,R9,R2 #---> R2:R8 = Z1 * Y0 (и довърши преобразуването) 38 005b C05451 ADDL2 R4,R1 # Преобразувай четвъртото произведение в беззнаково 39 005e C05551 ADDL2 R5,R1 40 0061 C05651 ADDL2 R6,R1 #---> C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 41 0064 D85752 ADWC R7,R2 #---> B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 42 0067 D80053 ADWC $0,R3 #---> A = ст.д.(Z1 * Y1) 43 006a C05851 ADDL2 R8,R1 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 44 006d D85A52 ADWC R10,R2 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 45 0070 D80053 ADWC $0,R3 46 0073 04 RET ==> we32k/um64x64.s <== # Multiply the 64-bit unsigned numbers in registers r3:r2 (Y1:Y0) and r1:r0 # (Z1:Z0) and return the 128-bit result in registers r3:r2:r1:r0 (A:B:C:D). # # No WE32K instruction returns the 32-bit mutiplication product high words. # Besides, the MULW3 instruction takes up to 205 cycles ("AT&T 382/385/3815 # Computers Assembly Language Programming Manual", p. 6-7). Thus the linear # algorithm from the book "Advanced Assembly Language", Peter Norton, 1991, # pp 229-230 is hard to apply and would be slow with the 20 multiplications # necessary when the MSW would have to be obtained by a special subroutine. # We replace it by an algorithm from the book "LSI MOS IC" by Kamen Filyov, # Ivan Zarkov and Nickolay Velchev, "Technica", Sofia, 1979, p. 294 (cyclic # and slower), the more so as the carry processing on the WE32K in a linear # programme is impossible as it lacks an "add with carry" type instruction. section .text .globl um64x64 um64x64() um64x64: 0: 10 44 SAVE %r4 # Save r4-r8 (see the aforementioned manual, p. A-79; 2: 84 42 44 MOVW %r2,%r4 # r4 = Y0 \\ note that we exclude r3 as it returns A) 5: 84 43 45 MOVW %r3,%r5 # r5 = Y1 8: 80 42 CLRW %r2 # Clear the high double word of the result a: 80 43 CLRW %r3 # A = B = 0 c: f8 40 01 46 ANDW3 %r0,&1,%r6 # Save the carry from the rightmost multiplier bit 10: d4 01 40 40 LRSW3 &1,%r0,%r0 # Shift the multiplier right by 1 bit - the low 14: c8 00 1f 41 40 INSFW &0,&31,%r1,%r0 19: d4 01 41 41 LRSW3 &1,%r1,%r1 # and the high words 1d: 84 6f 40 48 MOVW &64,%r8 # Set iteration count. Next instruction starts the loop 21: 28 46 L1: TSTW %r6 # Is there a carry from the multiplier? 23: 7f 19 BEB L3 # No, skip its processing 25: 80 46 CLRW %r6 # Yes, assume the addition won't give a carry 27: 9c 44 42 ADDW2 %r4,%r2 # Add the multiplicand to the partial product 2a: 53 0a BCCB L2 # No carry from the low words? Skip! 2c: 9c 01 43 ADDW2 &1,%r3 # Add the the high word carry to the low word 2f: 53 05 BCCB L2 # No carry from the high words? Skip! 31: 84 01 46 MOVW &1,%r6 # Save the carry from the high words 34: 9c 45 43 L2: ADDW2 %r5,%r3 # After the low words, add the high words too 37: 53 05 BCCB L3 # No carry from the high words? Skip! 39: 84 01 46 MOVW &1,%r6 # A " " " " " " " ? Save it! 3c: 84 46 47 L3: MOVW %r6,%r7 # Save the carry from the partial product 3f: f8 40 01 46 ANDW3 %r0,&1,%r6 # Save the carry from the rightmost bit 43: d4 01 40 40 LRSW3 &1,%r0,%r0 # Shift the partial product (129-bit!) shifting 47: c8 00 1f 41 40 INSFW &0,&31,%r1,%r0 # in the carries from each register on the left 4c: d4 01 41 41 LRSW3 &1,%r1,%r1 50: c8 00 1f 42 41 INSFW &0,&31,%r2,%r1 55: d4 01 42 42 LRSW3 &1,%r2,%r2 59: c8 00 1f 43 42 INSFW &0,&31,%r3,%r2 5e: d4 01 43 43 LRSW3 &1,%r3,%r3 62: c8 00 1f 47 43 INSFW &0,&31,%r7,%r3 # Put the carry from the sum in the highest bit 67: 70 NOP 68: 94 48 DECW %r8 # Any iterations left? 6a: 77 b7 BNEB L1 # Yes, continue the loop (loop body ends here) 6c: 04 c9 fc 4c MOVAW -4(%fp),%sp RESTORE %r4 # No (loop end). Restore r4-r8 for the calling function 70: 20 48 POPW %r8 72: 20 47 POPW %r7 74: 20 46 POPW %r6 76: 20 45 POPW %r5 78: 20 44 POPW %r4 7a: 20 49 POPW %fp 7c: 78 RSB # and return control to it. 7d: 70 NOP 7e: 70 NOP 7f: 70 NOP 68K GAS um64x64.s page 1 1 | 64-битовите числа без знак в регистри D3:D2 (Y1:Y0) и D1:D0 (Z1:Z0) да се 2 | умножат и 128-битовият резултат да се върне в рег. D3:D2:D1:D0 (A:B:C:D). 3 | Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 48E7 0F00 MOVEML %D4-%D7,-(%SP) | GCC изисква тези регистри да се съхраняват 8 0004 2A03 MOVEL %D3,%D5 | D5 = D3 = Y1, D0 = Z0 9 0006 C342 EXG %D1,%D2 | D1 = Y0, D2 = Z1 10 0008 4C00 5406 MULUL %D0,%D6:%D5 | D6:D5 = Z0 * Y1 11 000c 4C01 0404 MULUL %D1,%D4:%D0 | D4:D0 = C:D = Z0 * Y0 12 0010 4C02 1407 MULUL %D2,%D7:%D1 | D7:D1 = Z1 * Y0 13 0014 4C03 2403 MULUL %D3,%D3:%D2 | D3:D2 = Z1 * Y1 14 0018 D885 ADDL %D5,%D4 | C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 15 001a DF86 ADDXL %D6,%D7 | B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 16 001c 4285 CLRL %D5 17 001e D785 ADDXL %D5,%D3 | A = ст.д.(Z1 * Y1) 18 0020 D284 ADDL %D4,%D1 | C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 19 0022 D587 ADDXL %D7,%D2 | B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 20 0024 D785 ADDXL %D5,%D3 21 0026 4CDF 00F0 MOVEML (%SP)+,%D4-%D7 | Възстанови регистрите и върни управлението 22 002a 4E75 RTS x86 NASM um64x64.s 1 ; 64-битовите числа без знак в регистри EDX:ECX (Y1:Y0) и EBX:EAX (Z1:Z0) да се 2 ; умножат и 128-битовият резултат да се върне в рег. EDX:ECX:EBX:EAX (A:B:C:D). 3 ; Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 section .text 6 global _um64x64,um64x64 7 _um64x64: 8 um64x64: 9 00000000 56 PUSH ESI 10 00000001 57 PUSH EDI 11 00000002 55 PUSH EBP 12 00000003 89C6 MOV ESI,EAX ; Z0 13 00000005 89D7 MOV EDI,EDX ; Y1 14 00000007 52 PUSH EDX ; съхрани Y1 15 00000008 F7E1 MUL ECX ; Z0 * Y0 16 0000000A 96 XCHG EAX,ESI ; ESI = D = мл.д.(Z0 * Y0), EAX = Z0 17 0000000B 87D7 XCHG EDX,EDI ; EDI = C = ст.д.(Z0 * Y0), EDX = Y1 18 0000000D F7E2 MUL EDX ; Z0 * Y1, ст.дума е най-много 0xFFFFFFFE 19 0000000F 31ED XOR EBP,EBP ; A = 0 20 00000011 01C7 ADD EDI,EAX ; C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 21 00000013 11EA ADC EDX,EBP ; ст.д.(Z0 * Y1), сборът е най-много 0xFFFFFFFF, CF=0 22 00000015 87D1 XCHG EDX,ECX ; ECX = B = ст.д.(Z0 * Y1), EDX = Y0 23 00000017 89D8 MOV EAX,EBX ; Z1 24 00000019 F7E2 MUL EDX ; Z1 * Y0 25 0000001B 01C7 ADD EDI,EAX ; C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 26 0000001D 11D1 ADC ECX,EDX ; B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 27 0000001F 11ED ADC EBP,EBP ; A 28 00000021 97 XCHG EAX,EDI ; EAX = C 29 00000022 93 XCHG EAX,EBX ; EAX = Z1, EBX = C 30 00000023 5A POP EDX ; възстанови Y1 31 00000024 F7E2 MUL EDX ; Z1 * Y1 32 00000026 01C1 ADD ECX,EAX ; B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 33 00000028 11EA ADC EDX,EBP ; A = ст.д.(Z1 * Y1) 34 0000002A 96 XCHG EAX,ESI ; EAX = D 35 0000002B 5D POP EBP 36 0000002C 5F POP EDI 37 0000002D 5E POP ESI 38 0000002E C3 RET ARM GAS um64x64.s page 1 1 // 64-битовите числа без знак в регистри R3:R2 (Y1:Y0) и R1:R0 (Z1:Z0) да се 2 // умножат и 128-битовият резултат да се върне в рег. R3:R2:R1:R0 (A:B:C:D). 3 // Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 F0432DE9 STMFD SP!,{R4-R9,LR} //Съхрани използваните регистри (ARM IHI 0042F) 8 0004 905386E0 UMULL R5,R6,R0,R3 // R6:R5 = Z0 * Y1 9 0008 920084E0 UMULL R0,R4,R2,R0 // R4:R0 = C:D = Z0 * Y0 10 000c 917288E0 UMULL R7,R8,R1,R2 // R8:R7 = Z1 * Y0 11 0010 919383E0 UMULL R9,R3,R1,R3 // R3:R9 = Z1 * Y1 12 0014 051094E0 ADDS R1,R4,R5 // C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 13 0018 0820B6E0 ADCS R2,R6,R8 // B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 14 001c 0030A3E2 ADC R3,R3,#0 // A = ст.д.(Z1 * Y1) 15 0020 071091E0 ADDS R1,R1,R7// C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 16 0024 0920B2E0 ADCS R2,R2,R9// B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 17 0028 0030A3E2 ADC R3,R3,#0 18 002c F083BDE8 LDMFD SP!,{R4-R9,PC} // Възстанови регистрите и върни управлението ARC GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри r3:r2 (Y1:Y0) и r1:r0 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. r3:r2:r1:r0 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 1929 C800 MPYDU r8,r1,r3 # r9:r8 = Z1 * Y1 8 0004 1929 8600 MPYDU r6,r1,r2 # r7:r6 = Z1 * Y0 9 0008 1928 C400 MPYDU r4,r0,r3 # r5:r4 = Z0 * Y1 10 000c 1928 8000 MPYDU r0,r0,r2 # r1:r0 = C:D = Z0 * Y0 11 0010 0021 0181 ADD.F r1,r1,r4 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 12 0014 0125 C281 ADC.F r2,r5,r7 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 13 0018 4121 0310 ADC r3,r9,0 # A = ст.д.(Z1 * Y1) 14 001c 0021 8181 ADD.F r1,r1,r6 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 15 0020 0122 0282 ADC.F r2,r2,r8 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 16 0024 4123 0300 ADC r3,r3,0 17 0028 E07E J_S [blink] # Върни управлението PPC GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри r6:r5 (Y1:Y0) и r4:r3 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. r6:r5:r4:r3 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 7D233016 mulhwu r9,r3,r6 8 0004 7D0331D6 mullw r8,r3,r6 # r9:r8 = Z0 * Y1 9 0008 7CE32816 mulhwu r7,r3,r5 10 000c 7C6329D6 mullw r3,r3,r5 # r7:r3 = C:D = Z0 * Y0 11 0010 7D4429D6 mullw r10,r4,r5 12 0014 7D642816 mulhwu r11,r4,r5 # r11:r10 = Z1 * Y0 13 0018 7D8431D6 mullw r12,r4,r6 14 001c 7CC43016 mulhwu r6,r4,r6 # r6:r12 = Z1 * Y1 15 0020 7C874014 addc r4,r7,r8 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 16 0024 7CA95914 adde r5,r9,r11 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 17 0028 7CC60194 addze r6,r6 # A = ст.д.(Z1 * Y1) 18 002c 7C845014 addc r4,r4,r10# C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 19 0030 7CA56114 adde r5,r5,r12# B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 20 0034 7CC60194 addze r6,r6 21 0038 4E800020 blr # Върни управлението SPARC GAS um64x64.s page 1 1 ! 64-битовите числа без знак в регистри %o3:%o2 (Y1:Y0) и %o1:%o0 (Z1:Z0) да се 2 ! умножат и 128-битовият резултат да се върне в рег. %o3:%o2:%o1:%o0 (A:B:C:D). 3 ! Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 9DE3BFA0 save %sp,-96,%sp !davidlitchfield.com/sparc_buffer_overflows.pdf 8 0004 A256001B umul %i0,%i3,%l1 ! След „save“ изходните регистри стават входни! 9 0008 A5400000 rd %y,%l2 ! %l2:%l1 = Z0 * Y1 10 000c B056001A umul %i0,%i2,%i0 11 0010 A1400000 rd %y,%l0 ! %l0:%i0 = C:D = Z0 * Y0 12 0014 A656401A umul %i1,%i2,%l3 13 0018 A9400000 rd %y,%l4 ! %l4:%l3 = Z1 * Y0 14 001c AA56401B umul %i1,%i3,%l5 15 0020 B7400000 rd %y,%i3 ! %i3:%l5 = Z1 * Y1 16 0024 B2840011 addcc %l0,%l1,%i1 ! C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 17 0028 B4C48014 addxcc %l2,%l4,%i2 ! B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 18 002c B646C000 addx %i3,%g0,%i3 ! A = ст.д.(Z1 * Y1) 19 0030 B2864013 addcc %i1,%l3,%i1!C= ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 20 0034 B4C68015 addxcc %i2,%l5,%i2!B= ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 21 0038 B646C000 addx %i3,%g0,%i3 22 003c 81C7E008 ret 23 0040 81E80000 restore !Възстанови прозореца; изпълнява се преди „ret“ MIPS GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри $7:$6 (Y1:Y0) и $5:$4 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. $7:$6:$5:$4 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .ent um64x64 6 .global um64x64 7 um64x64: 8 0000 00870019 MULTU $4,$7 9 0004 00005010 MFHI $10 10 0008 00004812 MFLO $9 # $10:$9 = Z0 * Y1 11 000c 00860019 MULTU $4,$6 12 0010 00004010 MFHI $8 13 0014 00002012 MFLO $4 # $8:$4 = C:D = Z0 * Y0 14 0018 00A60019 MULTU $5,$6 15 001c 00006010 MFHI $12 16 0020 00005812 MFLO $11 # $12:$11 = Z1 * Y0 17 0024 00A70019 MULTU $5,$7 18 0028 00003810 MFHI $7 19 002c 00006812 MFLO $13 # $7:$13 = Z1 * Y1 20 0030 01092821 ADDU $5,$8,$9 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 21 0034 00A8702B SLTU $14,$5,$8 # Получи преноса 22 0038 014C3021 ADDU $6,$10,$12 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 23 003c 00CE3021 ADDU $6,$6,$14 # Отчети преноса 24 0040 00CA702B SLTU $14,$6,$10 # Получи преноса 25 0044 00EE3821 ADDU $7,$7,$14 # A = ст.д.(Z1 * Y1) 26 0048 00AB2821 ADDU $5,$5,$11# C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 27 004c 00AB702B SLTU $14,$5,$11 # Получи преноса 28 0050 00CD3021 ADDU $6,$6,$13# B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 29 0054 00CE3021 ADDU $6,$6,$14 # Отчети преноса 30 0058 00CD702B SLTU $14,$6,$13 # Получи преноса 31 ADDU $7,$7,$14 # Отчети преноса 32 005c 03E00008 00EE3821 JR $31 # Върни управлението 33 0064 00000000 00000000 00000000 .end um64x64 RISC-V GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри a3:a2 (Y1:Y0) и a1:a0 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. a3:a2:a1:a0 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 B307D502 MUL a5,a0,a3 8 0004 3338D502 MULHU a6,a0,a3 # a6:a5 = Z0 * Y1 9 0008 3337C502 MULHU a4,a0,a2 10 000c 3305C502 MUL a0,a0,a2 # a4:a0 = C:D = Z0 * Y0 11 0010 B3B2C502 MULHU t0,a1,a2 12 0014 B388C502 MUL a7,a1,a2 # t0:a7 = Z1 * Y0 13 0018 3383D502 MUL t1,a1,a3 14 001c B3B6D502 MULHU a3,a1,a3 # a3:t1 = Z1 * Y1 15 0020 B305F700 ADD a1,a4,a5 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 16 0024 B3B3E500 SLTU t2,a1,a4 # Получи преноса 17 0028 33065800 ADD a2,a6,t0 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 18 002c 1E96 ADD a2,a2,t2 # Отчети преноса 19 002e B3330601 SLTU t2,a2,a6 # Получи преноса 20 0032 9E96 ADD a3,a3,t2 # A = ст.д.(Z1 * Y1) 21 0034 C695 ADD a1,a1,a7 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 22 0036 B3B31501 SLTU t2,a1,a7 # Получи преноса 23 003a 1A96 ADD a2,a2,t1 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 24 003c 1E96 ADD a2,a2,t2 # Отчети преноса 25 003e B3336600 SLTU t2,a2,t1 # Получи преноса 26 0042 9E96 ADD a3,a3,t2 # Отчети преноса 27 0044 8280 RET # Върни управлението Nios II GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри r7:r6 (Y1:Y0) и r5:r4 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. r7:r6:r5:r4 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 3A38D321 MUL r9,r4,r7 8 0004 3A38D421 MULXUU r10,r4,r7 # r10:r9 = Z0 * Y1 9 0008 3A389021 MULXUU r8,r4,r6 10 000c 3A388921 MUL r4,r4,r6 # r8:r4 = C:D = Z0 * Y0 11 0010 3A389829 MULXUU r12,r5,r6 12 0014 3A389729 MUL r11,r5,r6 # r12:r11 = Z1 * Y0 13 0018 3A38DB29 MUL r13,r5,r7 14 001c 3A38CE29 MULXUU r7,r5,r7 # r7:r13 = Z1 * Y1 15 0020 3A884B42 ADD r5,r8,r9 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 16 0024 3A801D2A CMPLTU r14,r5,r8 # Получи преноса 17 0028 3A880D53 ADD r6,r10,r12 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 18 002c 3A888D33 ADD r6,r6,r14 # Отчети преноса 19 0030 3A809D32 CMPLTU r14,r6,r10 # Получи преноса 20 0034 3A888F3B ADD r7,r7,r14 # A = ст.д.(Z1 * Y1) 21 0038 3A88CB2A ADD r5,r5,r11# C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 22 003c 3A80DD2A CMPLTU r14,r5,r11 # Получи преноса 23 0040 3A884D33 ADD r6,r6,r13# B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 24 0044 3A888D33 ADD r6,r6,r14 # Отчети преноса 25 0048 3A805D33 CMPLTU r14,r6,r13 # Получи преноса 26 004c 3A888F3B ADD r7,r7,r14 # Отчети преноса 27 0050 3A2800F8 RET Xtensa GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри a5:a4 (Y1:Y0) и a3:a2 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. a5:a4:a3:a2 (A:B:C:D). 3 # 4 # Нито асемблерът, нито „щатният“ QEMU поддържат командата „MULUH“. А и при 5 # наличието само на 16 регистъра би се наложило да се използва прозоречният 6 # режим за извикване на фукнцията, която би заместила „MULUH“. Затова, този 7 # алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 8 # (линеен) е много трудно приложим. Заместваме го с алгоритъм от книгата на 9 # Камен Фильов, Иван Зарков и Николай Велчев „Големи МОС интегрални схеми“, 10 # издателство „Техника“, София, 1979 г., стр. 294 (цикличен и по-бавен) – и 11 # без това обработката на преноса в Xtensa е невъзможна в линейна програма. 12 13 .global um64x64 14 um64x64: 15 0000 6D04 MOV a6,a4 # a6 = Y0 16 0002 7D05 MOV a7,a5 # a7 = Y1 17 0004 0C04 MOVI a4,0 # Изчисти старшата двойна дума на резултата 18 0006 52A000 MOVI a5,0 # A = B = 0 19 0009 A2A001 MOVI a10,1 # Надясно ще изместваме с 1 по двоичен разред 20 000c 000A40 SSR a10 21 000f A08210 AND a8,a2,a10#Съхрани преноса от най-младшия бит на множителя 22 0012 202381 SRC a2,a3,a2# Измести множителя с 1 бит надясно – младшата 23 0015 303091 SRL a3,a3 # и старшата дума 24 0018 92A040 MOVI a9,64 # Задай брой итерации, 25 001b 768926 LOOP a9,L3 # начало и край на цикъла 26 001e 9C28 BEQZ a8,L2 # Начало на цикъла. Преносът от множителя 0? Прескочи! 27 0020 0C08 MOVI a8,0 # Приеми, че пренос от събирането няма да има 28 0022 6A44 ADD a4,a4,a6 # Добави множимото към частичното произведение 29 0024 67B405 BGEU a4,a6,L1 # Няма пренос от младшите думи? Прескочи! 30 0027 52C501 ADDI a5,a5,1 # Добави към старшата дума преноса от младшата 31 002a 508A83 MOVEQZ a8,a10,a5 # Има пренос от старшата дума? Отбележи го! 32 002d 7A55 L1: ADD a5,a5,a7 # След младшите думи събери и старшите 33 002f 77B501 BGEU a5,a7,L2 # Няма пренос от старшите думи? Прескочи! 34 0032 0C18 MOVI a8,1 # Има " " " " " " – отбележи го 35 0034 9D08 L2: MOV a9,a8 # Запази преноса от частичното произведение 36 0036 A08210 AND a8,a2,a10 # Съхрани преноса отдясно 37 0039 202381 SRC a2,a3,a2 # Измести частичното произведение (129 бита!) 38 003c 303481 SRC a3,a4,a3 39 003f 404581 SRC a4,a5,a4 40 0042 505981 SRC a5,a9,a5# Край на цикъла. Вмъкни преноса от сбора най-вляво! 41 0045 0DF0 L3: RET # Върни управлението 88K GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри r5:r4 (Y1:Y0) и r3:r2 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. r5:r4:r3:r2 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 # 5 # В M88K старшите думи на произведението са недостъпни, затова ги получаваме 6 # както е показано на http://icodeguru.com/Embedded/Hacker's-Delight/054.htm 7 # (алгоритъмът е от фиг. 8-2 на книгата на Henry Warren „Hacker's Delight“): 8 # 9 # int mulhu(int u, int v) 10 # { 11 # unsigned u0, u1, v0, v1, w0, w1, w2, t; 12 # 13 # u0 = u & 0xFFFF; 14 # u1 = u >> 16; 15 # v0 = v & 0xFFFF; 16 # v1 = v >> 16; 17 # w0 = u0 * v0; 18 # t = u1 * v0 + (w0 >> 16); 19 # w1 = t & 0xFFFF; 20 # w2 = t >> 16; 21 # w1 = u0 * v1 + w1; 22 # return u1 * v1 + w2 + (w1 >> 16); 23 # } 24 0000 458A0000 # // u = r10, v = r11 25 0004 F1AA9810 MULHU: and.u r12,r10,0 # u0 = u & 0xFFFF; 26 0008 45CB0000 extu r13,r10,0<16> # u1 = u >> 16; 27 000c F1EB9810 and.u r14,r11,0 # v0 = v & 0xFFFF; 28 0010 F60C6C0E extu r15,r11,0<16> # v1 = v >> 16; 29 0014 F62D6C0E mul r16,r12,r14 # w0 = u0 * v0; 30 0018 F2109810 mul r17,r13,r14 # t = u1 * v0 31 001c F6316010 extu r16,r16,0<16> # w0 >>= 16; 32 0020 46510000 addu r17,r17,r16 # t += w0; 33 0024 F2719810 and.u r18,r17,0 # w1 = t & 0xFFFF; 34 0028 F58C6C0F extu r19,r17,0<16> # w2 = t >> 16; 35 002c F652600C mul r12,r12,r15 # u0 *= v1; 36 0030 F5AD6C0F addu r18,r18,r12 # w1 += u0; 37 0034 F5AD6013 mul r13,r13,r15 # u1 *= v1; 38 0038 F2529810 addu r13,r13,r19 # u1 += w2; 39 003c F54D6012 extu r18,r18,0<16> # w1 >>= 16; 40 0040 F400C001 addu r10,r13,r18 # return u1 + w1; // r10 41 jmp r1 # Върни управлението 42 43 .global _um64x64 44 0044 67FF001C _um64x64: 45 0048 243F0000 subu sp,sp,28 # Съхрани използваните регистри 46 004c 25DF0004 st r1,sp,0 47 0050 25FF0008 st r14,sp,4 48 0054 261F000C st r15,sp,8 49 0058 263F0010 st r16,sp,12 50 005c 265F0014 st r17,sp,16 51 0060 267F0018 st r18,sp,20 52 0064 F5425800 st r19,sp,24 53 0068 F5655800 or r10,r2,r0 54 006c CBFFFFE5 or r11,r5,r0 55 0070 F4EA5800 bsr MULHU 56 0074 F5425800 or r7,r10,r0 # r7 = ст.д.(Z0 * Y1) 57 0078 F5645800 or r10,r2,r0 58 007c CBFFFFE1 or r11,r4,r0 59 0080 F50A5800 bsr MULHU 60 0084 F5435800 or r8,r10,r0 # r8 = C = ст.д.(Z0 * Y0) 61 0088 F5645800 or r10,r3,r0 62 008c CBFFFFDD or r11,r4,r0 63 0090 F52A5800 bsr MULHU 64 0094 F5435800 or r9,r10,r0 # r9 = ст.д.(Z1 * Y0) 65 0098 F5655800 or r10,r3,r0 66 009c CBFFFFD9 or r11,r5,r0 67 00a0 F4C26C05 bsr MULHU 68 00a4 F5836C05 mul r6,r2,r5 # r7:r6 = Z0 * Y1 69 00a8 F4AA5800 mul r12,r3,r5 # r12 = мл.д.(Z1 * Y1) 70 00ac F4426C04 or r5,r10,r0 # r5:r12 = Z1 * Y1 71 00b0 F5436C04 mul r2,r2,r4 # r8:r2 = C:D = Z0 * Y0 72 00b4 F4686106 mul r10,r3,r4 # r9:r10 = Z1 * Y0 73 00b8 F4876309 addu.co r3,r8,r6 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 74 00bc F4A56200 addu.cio r4,r7,r9 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 75 00c0 F463610A addu.ci r5,r5,r0 # A = ст.д.(Z1 * Y1) 76 00c4 F484630C addu.co r3,r3,r10# C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 77 00c8 F4A56200 addu.cio r4,r4,r12#B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 78 00cc 167F0018 addu.ci r5,r5,r0 79 00d0 165F0014 ld r19,sp,24 # Възстанови регистрите и върни управлението 80 00d4 163F0010 ld r18,sp,20 81 00d8 161F000C ld r17,sp,16 82 00dc 15FF0008 ld r16,sp,12 83 00e0 15DF0004 ld r15,sp,8 84 00e4 143F0000 ld r14,sp,4 85 00e8 63FF001C ld r1,sp,0 86 00ec F400C001 addu sp,sp,28 jmp r1 Or1k GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри R6:R5 (Y1:Y0) и R4:R3 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. R6:R5:R4:R3 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 # 5 # Командата L.MFSPR R8,R0,5 << 11 | 2 за четене на MACHI изисква бит SUMRA на 6 # SR да е 1, но след RESET той е 0. Излиза, че в потребителския режим дългото 7 # умножение е неизползваемо! Затова сме принудени да получаваме старшите думи 8 # както е показано на http://icodeguru.com/Embedded/Hacker's-Delight/054.htm 9 # (алгоритъмът е от фиг. 8-2 на книгата на Henry Warren „Hacker's Delight“): 10 # 11 # int mulhu(int u, int v) 12 # { 13 # unsigned u0, u1, v0, v1, w0, w1, w2, t; 14 # 15 # u0 = u & 0xFFFF; 16 # u1 = u >> 16; 17 # v0 = v & 0xFFFF; 18 # v1 = v >> 16; 19 # w0 = u0 * v0; 20 # t = u1 * v0 + (w0 >> 16); 21 # w1 = t & 0xFFFF; 22 # w2 = t >> 16; 23 # w1 = u0 * v1 + w1; 24 # return u1 * v1 + w2 + (w1 >> 16); 25 # } 26 # // u = R13, v = R15 27 0000 A62DFFFF MULHU: L.ANDI R17,R13,0xFFFF # u0 = u & 0xFFFF; 28 0004 BA6D0050 L.SRLI R19,R13,16 # u1 = u >> 16; 29 0008 A6AFFFFF L.ANDI R21,R15,0xFFFF # v0 = v & 0xFFFF; 30 000c BAEF0050 L.SRLI R23,R15,16 # v1 = v >> 16; 31 0010 E331AB0B L.MULU R25,R17,R21 # w0 = u0 * v0; 32 0014 E373AB0B L.MULU R27,R19,R21 # t = u1 * v0 33 0018 BB390050 L.SRLI R25,R25,16 # w0 >>= 16; 34 001c E37BC800 L.ADD R27,R27,R25 # t += w0; 35 0020 A7BBFFFF L.ANDI R29,R27,0xFFFF # w1 = t & 0xFFFF; 36 0024 BBFB0050 L.SRLI R31,R27,16 # w2 = t >> 16; 37 0028 E231BB0B L.MULU R17,R17,R23 # u0 *= v1; 38 002c E3BD8800 L.ADD R29,R29,R17 # w1 += u0; 39 0030 E273BB0B L.MULU R19,R19,R23 # u1 *= v1; 40 0034 E273F800 L.ADD R19,R19,R31 # u1 += w2; 41 0038 BBBD0050 L.SRLI R29,R29,16 # w1 >>= 16; 42 003c 44004800 L.JR LR # Върни управлението (изпълн. се след „L.ADD“!) 43 0040 E1B3E800 L.ADD R13,R19,R29 # return u1 + w1; // R13 44 45 .global um64x64 46 um64x64: 47 0044 D7E14FFC L.SW -4(SP),LR # Съхрани LR, защото „L.JAL“ ще го промени! 48 0048 E1A30004 L.OR R13,R3,R0 49 004c 07FFFFED L.JAL MULHU 50 0050 E1E60004 L.OR R15,R6,R0 # Изпълнява се преди „L.JAL“! 51 0054 E10D0004 L.OR R8,R13,R0 # R8 = ст.д.(Z0 * Y1) 52 0058 E1A30004 L.OR R13,R3,R0 53 005c 07FFFFE9 L.JAL MULHU 54 0060 E1E50004 L.OR R15,R5,R0 # Изпълнява се преди „L.JAL“! 55 0064 E16D0004 L.OR R11,R13,R0 # R11 = C = ст.д.(Z0 * Y0) 56 0068 E1A40004 L.OR R13,R4,R0 57 006c 07FFFFE5 L.JAL MULHU 58 0070 E1E50004 L.OR R15,R5,R0 # Изпълнява се преди „L.JAL“! 59 0074 E18D0004 L.OR R12,R13,R0 # R12 = ст.д.(Z1 * Y0) 60 0078 E1A40004 L.OR R13,R4,R0 61 007c 07FFFFE1 L.JAL MULHU 62 0080 E1E60004 L.OR R15,R6,R0 # Изпълнява се преди „L.JAL“! 63 0084 E0E3330B L.MULU R7,R3,R6 # R8:R7 = Z0 * Y1 64 0088 E224330B L.MULU R17,R4,R6 # R17 = мл.д.(Z1 * Y1) 65 008c E0CD0004 L.OR R6,R13,R0 # R6:R17 = Z1 * Y1 66 0090 E0632B0B L.MULU R3,R3,R5 # R11:R3 = C:D = Z0 * Y0 67 0094 E1A42B0B L.MULU R13,R4,R5 # R12:R13 = Z1 * Y0 68 0098 E08B3800 L.ADD R4,R11,R7 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 69 009c E0A86001 L.ADDC R5,R8,R12 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 70 00a0 E0C60001 L.ADDC R6,R6,R0 # A = ст.д.(Z1 * Y1) 71 00a4 E0846800 L.ADD R4,R4,R13# C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 72 00a8 E0A58801 L.ADDC R5,R5,R17# B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 73 00ac 8521FFFC L.LWZ LR,-4(SP) # Възстанови LR 74 00b0 44004800 L.JR LR # Върни управлението 75 00b4 E0C60001 L.ADDC R6,R6,R0 # Изпълнява се преди „L.JR“! 76 77 /* А ето как би могло да изглежда решението при SUMRA = 1 (неизпробвано!): 78 L.MACRC R7 79 L.MACU R3,R6 80 L.MFSPR R8,R0,5 << 11 | 2 # MACHI 81 L.MACRC R7 # R8:R7 = Z0 * Y1 82 L.MACU R3,R5 83 L.MFSPR R11,R0,5 << 11 | 2 84 L.MACRC R3 # R11:R3 = C:D = Z0 * Y0 85 L.MACU R4,R5 86 L.MFSPR R12,R0,5 << 11 | 2 87 L.MACRC R13 # R12:R13 = Z1 * Y0 88 L.MACU R4,R6 89 L.MFSPR R6,R0,5 << 11 | 2 90 L.MACRC R17 # R6:R17 = Z1 * Y1 91 L.ADD R4,R11,R7 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 92 L.ADDC R5,R8,R12 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 93 L.ADDC R6,R6,R0 # A = ст.д.(Z1 * Y1) 94 L.ADD R4,R4,R13# C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 95 L.ADDC R5,R5,R17# B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 96 L.JR LR # Върни управлението 97 L.ADDC R6,R6,R0 # Изпълнява се преди „L.JR“! 98 */ Xilinx MicroBlaze GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри R8:R7 (Y1:Y0) и R6:R5 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. R8:R7:R6:R5 (A:B:C:D). 3 # Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 03406541 MULHU R11,R5,R8 8 0004 00404541 MUL R10,R5,R8 # R11:R10 = Z0 * Y1 9 0008 03382541 MULHU R9,R5,R7 10 000c 0038A540 MUL R5,R5,R7 # R9:R5 = C:D = Z0 * Y0 11 0010 00388641 MUL R12,R6,R7 12 0014 03386640 MULHU R3,R6,R7 # R3:R12 = Z1 * Y0 13 0018 00408640 MUL R4,R6,R8 14 001c 03400641 MULHU R8,R6,R8 # R8:R4 = Z1 * Y1 15 0020 0050C900 ADD R6,R9,R10 # C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 16 0024 0018EB08 ADDC R7,R11,R3 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 17 0028 00000809 ADDC R8,R8,R0 # A = ст.д.(Z1 * Y1) 18 002c 0060C600 ADD R6,R6,R12# C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 19 0030 0020E708 ADDC R7,R7,R4 # B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 20 0034 08000FB6 RTSD R15,8 # Върни управлението 21 0038 00000809 ADDC R8,R8,R0 # Изпълнява се преди „RTSD“! HPPA GAS um64x64.s page 1 1 ; 64-битовите числа без знак в регистри R23:R24 (Y1:Y0) и R25:R26 (Z1:Z0) да се 2 ; умножат и 128-битовият резултат да се върне в рег. R23:R24:R25:R26 (A:B:C:D). 3 ; Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .text 6 .global um64x64 7 um64x64: 8 0000 0FD71281 STW %R23,-16(%SP) ; Връзката между целочислените регистри и тези за 9 0004 0FD81289 STW %R24,-12(%SP) ; числа с плаваща запетая става само през паметта 10 0008 2FC11016 FLDDS -16(%SP),%FR22 ; FR22 = Y 11 000c 0FD91281 STW %R25,-16(%SP) ; Съхрани аргументите в стека и ги зареди 12 0010 0FDA1289 STW %R26,-12(%SP) ; в регистрите за числа с плаваща запетая 13 0014 2FC11017 FLDDS -16(%SP),%FR23 ; FR23 = Z 14 0018 3AF64798 XMPYU %FR23R,%FR22L,%FR24 ; FR24 = Z0 * Y1 15 001c 3AF65799 XMPYU %FR23R,%FR22R,%FR25 ; FR25 = Z0 * Y0 16 0020 3AF6571A XMPYU %FR23L,%FR22R,%FR26 ; FR26 = Z1 * Y0 17 0024 3AF6471B XMPYU %FR23L,%FR22L,%FR27 ; FR27 = Z1 * Y1 18 0028 2FC11218 FSTDS %FR24,-16(%SP) 19 002c 0FC11093 LDW -16(%SP),%R19 20 0030 0FC91094 LDW -12(%SP),%R20 ; R19:R20 = Z0 * Y1 21 0034 2FC11219 FSTDS %FR25,-16(%SP) 22 0038 0FC11095 LDW -16(%SP),%R21 23 003c 0FC9109A LDW -12(%SP),%R26 ; R21:R26 = C:D = Z0 * Y0 24 0040 2FC1121A FSTDS %FR26,-16(%SP) 25 0044 0FC11096 LDW -16(%SP),%R22 26 0048 0FC9109F LDW -12(%SP),%R31 ; R22:R31 = Z1 * Y0 27 004c 2FC1121B FSTDS %FR27,-16(%SP) 28 0050 0FC11097 LDW -16(%SP),%R23 29 0054 0FC91081 LDW -12(%SP),%R1 ; R23:R1 = Z1 * Y1 30 0058 0A950619 ADD %R21,%R20,%R25 ; C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 31 005c 0AD30718 ADDC %R19,%R22,%R24 ; B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 32 0060 08170717 ADDC %R23,%R0,%R23 ; A = ст.д.(Z1 * Y1) 33 0064 0BF90619 ADD %R25,%R31,%R25;C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 34 0068 08380718 ADDC %R24,%R1,%R24;B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 35 006c 08170717 ADDC %R23,%R0,%R23 36 0070 E840C000 BV (%R2) ; Върни управлението 37 0074 08000240 NOP Renesas / SuperH SH GAS Little Endian um64x64.s page 1 1 ! 64-битовите числа без знак в регистри R7:R6 (Y1:Y0) и R5:R4 (Z1:Z0) да се 2 ! умножат и 128-битовият резултат да се върне в рег. R7:R6:R5:R4 (A:B:C:D). 3 ! Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 4537 DMULU.L R4,R7 8 0002 1A01 STS MACL,R1 9 0004 0A02 STS MACH,R2 ! R2:R1 = Z0 * Y1 10 0006 6534 DMULU.L R6,R4 11 0008 1A04 STS MACL,R4 12 000a 0A00 STS MACH,R0 ! R0:R4 = C:D = Z0 * Y0 13 000c 5536 DMULU.L R5,R6 14 000e 1A03 STS MACL,R3 15 0010 0A06 STS MACH,R6 ! R6:R3 = Z1 * Y0 16 0012 5537 DMULU.L R5,R7 17 0014 1A05 STS MACL,R5 18 0016 0A07 STS MACH,R7 ! R7:R5 = Z1 * Y1 19 0018 0800 CLRT 20 001a 0E31 ADDC R0,R1 ! C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 21 001c 2E36 ADDC R2,R6 ! B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 22 001e 00E0 MOV #0,R0 23 0020 0E37 ADDC R0,R7 ! A = ст.д.(Z1 * Y1) 24 0022 0800 CLRT 25 0024 3E31 ADDC R3,R1 ! C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 26 0026 5E36 ADDC R5,R6 ! B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 27 0028 0E37 ADDC R0,R7 28 002a 0B00 RTS ! Върни управлението (изпълнява се след „MOV“!) 29 002c 1365 MOV R1,R5 ! R5 = C GAS for CRIS um64x64.s page 1 1 ; 64-битовите числа без знак в регистри R13:R12 (Y1:Y0) и R11:R10 (Z1:Z0) да се 2 ; умножат и 128-битовият резултат да се върне в рег. R13:R12:R11:R10 (A:B:C:D). 3 ; Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 5 .global um64x64 6 um64x64: 7 0000 90E2 SUBQ 16,$SP ; Съхрани R0–R3 (ETRAX FS Designer’s Reference, стр.212 8 0002 FE3B MOVEM $R3,[$SP] 9 0004 6D36 MOVE.D $R13,$R3; Y1 10 0006 2A39 MULU.D $R10,$R3 11 0008 7076 MOVE $MOF,$R0; R0:R3 = Z0 * Y1 12 000a 2CA9 MULU.D $R12,$R10 13 000c 7176 MOVE $MOF,$R1; R1:R10 = C:D = Z0 * Y0 14 000e 2BC9 MULU.D $R11,$R12 15 0010 7276 MOVE $MOF,$R2; R2:R12 = Z1 * Y0 16 0012 2DB9 MULU.D $R13,$R11 17 0014 7D76 MOVE $MOF,$R13;R13:R11 = Z1 * Y1 18 0016 2136 ADD.D $R1,$R3 ; C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) 19 0018 7025 ADDC $R0,$R2 ; B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) 20 001a 7086 CLEAR.D $R0 21 001c 70D5 ADDC $R0,$R13; A = ст.д.(Z1 * Y1) 22 001e 2C36 ADD.D $R12,$R3; C = ст.д.(Z0 * Y0) + мл.д.(Z0 * Y1) + мл.д.(Z1 * Y0) 23 0020 7B25 ADDC $R11,$R2; B = ст.д.(Z0 * Y1) + ст.д.(Z1 * Y0) + мл.д.(Z1 * Y1) 24 0022 70D5 ADDC $R0,$R13 25 0024 63B6 MOVE.D $R3,$R11; R11 = C 26 0026 62C6 MOVE.D $R2,$R12; R12 = B 27 0028 F0B9 RET ; Възстанови съхранените регистри и върни управлението 28 002a BE3F MOVEM [$SP+],$R3; Изпълнява се преди „RET“! BFIN GAS um64x64.s page 1 1 # 64-битовите числа без знак в регистри R3:R2 (Y1:Y0) и R1:R0 (Z1:Z0) да се 2 # умножат и 128-битовият резултат да се върне в рег. R3:R2:R1:R0 (A:B:C:D). 3 # 4 # Blackfin няма команда за старшата дума на произведението, пък и 8 даннови 5 # регистъра не стигат за варианта с функция за получаването му. Затова този 6 # алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 7 # (линеен) е много трудно приложим. Заместваме го с алгоритъм от книгата на 8 # Камен Фильов, Иван Зарков и Николай Велчев „Големи МОС интегрални схеми“, 9 # издателство „Техника“, София, 1979 г., стр. 294 (цикличен и по-бавен) – и 10 # без това обработка на преноса в Blackfin е невъзможна в линейна програма. 11 12 .global _um64x64 13 _um64x64: 14 0000 E305 [--SP] = (R7:4, P5:3);# Съхрани R4–R7/P3–P5 (82-000410-03, стр. 1-433) 15 0002 2230 R4 = R2; # Y0 16 0004 2B30 R5 = R3; # Y1 17 0006 9258 R2 = R2 ^ R2; # Изчисти старшата двойна дума на резултата 18 0008 DB58 R3 = R3 ^ R3; # A = B = 0 19 000a 0C03 CC = AC0; # CC = 0 20 000c 82C6F9C3 R1 = ROT R1 BY -1;# Измести множителя с 1 бит надясно – старшата 21 0010 82C6F8C1 R0 = ROT R0 BY -1;# и младшата дума 22 0014 28E14000 P0 = 64; # Задай брой итерации, начало и край на цикъла 23 0018 A2E01000 LSETUP (L_1, L_4) LC0 = P0; 24 001c 0810 L_1: IF !CC JUMP L_3;# Начало на цикъла. Преносът от множителя 0? Прескочи! 25 001e A250 R2 = R2 + R4; # Добави множимото към частичното произведение 26 0020 0C03 CC = AC0; # Има ли пренос от младшите думи? 27 0022 0310 IF !CC JUMP L_2; # Ако не, прескочи 28 0024 0B64 R3 += 1; # Добави към старшата дума преноса от младшата 29 0026 0C03 CC = AC0; # Съхрани преноса от старшата дума 30 0028 EB50 L_2: R3 = R3 + R5; # След младшите думи събери и старшите 31 002a 2C03 CC |= AC0; # Добави (логически) преноса от старшите думи 32 002c 82C6FBC7 L_3: R3 = ROT R3 BY -1; # Измести частичното произведение (129 бита!) 33 0030 82C6FAC5 R2 = ROT R2 BY -1; 34 0034 82C6F9C3 R1 = ROT R1 BY -1; 35 0038 82C6F8C1 L_4: R0 = ROT R0 BY -1; # Край на цикъла 36 003c A305 (R7:4, P5:3) = [SP++];# Възстанови съхранените регистри 37 003e 1000 RTS; # Върни управлението Hexagon GAS um64x64.s page 1 1 // 64-битовите числа без знак в регистри R3:R2 (Y1:Y0) и R1:R0 (Z1:Z0) да се 2 // умножат и 128-битовият резултат да се върне в рег. R3:R2:R1:R0 (A:B:C:D). 3 // Алгоритъм: Peter Norton, "Advanced Assembly Language", 1991, стр. 229-230 4 // 5 // След умноженията се получава следното разположение на данните по регистри: 6 // _____ 7 // __|R1:R0| 8 // |R5:R4| 9 // __|R7:R6| 10 // |R3:R2| 11 12 .global um64x64 13 um64x64: 14 { R5:4 = MPYU(R0,R3) // Z0 * Y1 15 0000 044340E5 06C241E5 R7:6 = MPYU(R1,R2) } // Z1 * Y0 16 { R3:2 = MPYU(R1,R3) // Z1 * Y1 = A:B 17 R1:0 = MPYU(R0,R2) // Z0 * Y0 = C:D 18 P0 = CMP.GT(R0,R0) // Нулирай входните преноси 19 0008 024341E5 004240E5 004040F2 01C040F2 P1 = CMP.GT(R0,R0) } 20 { R5:4 = ADD(R5:4,R7:6,P0):CARRY // B:C = Z0 * Y1 + Z1 * Y0 21 R6 = R1 22 0018 0446C4C2 27301630 R7 = R2 } 23 0020 24C6C4C2 R5:4 = ADD(R5:4,R7:6,P1):CARRY//B:C += мл.д.(Z1 * Y1) : ст.д.(Z0 * Y0) 24 { IF (P0) R3 = ADD(R3,#1) // Отчети преносите (не може и двата да ги има) 25 IF (P1) R3 = ADD(R3,#1) // A 26 R2 = R5 // B 27 0024 23400374 23402374 41305230 R1 = R4 } // C 28 0030 00C09F52 JUMPR LR // Върни управлението S/390 GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри 2:3 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри 2:3 и 4:5. 4 5 .global absdif64 6 absdif64: 7 0000 1924 CR 2,4 # Сравни старшите думи 8 0002 A7440007 JL L1 # Умаляемото е по-малко от умалителя - извади него 9 0006 A724000B JH L2 # Умаляемото е по-голямо от умалителя - извади от него 10 000a 1535 CLR 3,5 # Старшите думи са равни - сравни младшите 11 000c A7B40008 JNL L2 # Умаляемото е не по-малко от умалителя 12 0010 1F53 L1: SLR 5,3 # Извади младшите 13 0012 B9990042 SLBR 4,2 # и старшите думи на умаляемото от умалителя 14 0016 1824 LR 2,4 15 0018 1835 LR 3,5 # Върни резултата в 2:3 16 001a 07FE BR 14 17 001c 1F35 L2: SLR 3,5 # Извади младшите 18 001e B9990024 SLBR 2,4 # и старшите думи на умалителя от умаляемото 19 0022 07FE BR 14 ==> id32/absdif64.s <== 1 * Return in *7(16) the absolute value of the difference between the signed 2 * double words in 7(0):7(4) -> registers 0:1 and 7(8):7(12) -> registes 2:3. 3 4 entry absdif64 00000000d 5 absdif64 equ * 00000d 5807 0000 6 l 0,0(7) High word of the first double word 00004d 5817 0004 7 l 1,4(7) Low " " " " " " " " 00008d 5827 0008 8 l 2,8(7) High" " " "second " " " 0000Cd 5837 000C 9 l 3,12(7) Low " " " " " " " " 00010d 5847 0010 10 l 4,16(7) The address where the absolute value must be returned 00014d 0902 11 cr 0,2 Compare the high words 00016d 2114 0000001Ed 12 bms L1 The minuend is less than the subtrahend 00018d 212C 00000030d 13 bps L3 The minuend is greater than the subtrahend 0001Ad 0513 14 clr 1,3 The high words are equal - compare the low words 0001Cd 238A 00000030d 15 bnls L3 The munuend is not less than the subtrahend 0001Ed 0B31 16 L1 sr 3,1 The minuend less than the subtrahend: subtract low... 00020d 2382 00000024d 17 bncs L2 (No borrow? Skip! 00022d 2721 18 sis 2,1 Borrow - take it from the high word) 00024d 0B20 19 L2 sr 2,0 ...and high words of the minuend from the subtrahend 00026d 5024 0000 20 st 2,0(4) Write the high 0002Ad 5034 0004 21 st 3,4(4) and the low word of the absolute value 0002Ed 030F 22 br 15 Return to the calling function 00030d 0B13 23 L3 sr 1,3 Subtract the low and... 00032d 2382 00000036d 24 bncs L4 (No borrow? Skip! 00034d 2701 25 sis 0,1 Borrow - take it from the high word) 00036d 0B02 26 L4 sr 0,2 ...the high words of the minuend from the subtrahend 00038d 5004 0000 27 st 0,0(4) Write the high 0003Cd 5014 0004 28 st 1,4(4) and the low word of the absolute value 00040d 030F 29 br 15 Return to the calling function VAX GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри R1:R0 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # AP(4) -> R1:R0 и AP(12) -> R3:R2. 4 5 .global _absdif64 6 _absdif64: 7 0000 3C00 .word 0x3C # R2-R5 8 0002 FD7DAC04 50 MOVO 4(AP),R0# Аргументите в регистри 9 0007 D15153 CMPL R1,R3 # Сравни старшите думи 10 000a 1907 BLSS L1 # Умаляемото е по-малко от умалителя - размени ги 11 000c 140C BGTR L2 # Умаляемото е по-голямо от умалителя - извади ги 12 000e D15052 CMPL R0,R2 # Старшите думи са равни - сравни младшите 13 0011 1E07 BGEQU L2 # Умаляемото е не по-малко от умалителя 14 0013 7D5054 L1: MOVQ R0,R4 # Размени двойните думи (R5:R4 = R1:R0, 15 0016 FD7D5250 MOVO R2,R0 # R3:R2:R1:R0 = R5:R4:R3:R2) 16 001a C25250 L2: SUBL2 R2,R0 # Извади младшите 17 001d D95351 SBWC R3,R1 # и старшите думи на умалителя от умаляемото 18 0020 04010101 RET ==> we32k/absdif64.s <== # Return in registers r0:r1 the absolute value of the difference between the # signed double words in ap(0):ap(4) -> r0:r1 and ap(8):ap(12) -> r2:r3. section .text .globl absdif64 absdif64() absdif64: 0: a0 43 PUSHW %r3 # "AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 40 MOVW 0(%ap),%r0 # Programming Manual", pp. 6-13, 6-14 5: 84 74 41 MOVW 4(%ap),%r1 8: 84 78 42 MOVW 8(%ap),%r2 b: 84 7c 43 MOVW 12(%ap),%r3 e: 3c 42 40 CMPW %r2,%r0 # Compare the high words 11: 4b 09 BLB L1 # The minuend is less than the subtrahend 13: 47 15 BGB L3 # The minuend is greater than the subtrahend 15: 3c 43 41 CMPW %r3,%r1 # The high words are equal - compare the low words 18: 53 10 BGEUB L3 # The munuend is not less than the subtrahend 1a: fc 41 43 41 L1: SUBW3 %r1,%r3,%r1# The minuend < the subtrahend: subtract low and... 1e: 53 04 BCCB L2 # (No borrow? Skip! 20: 94 42 DECW %r2 # Borrow - take it from the high word) 22: fc 40 42 40 L2: SUBW3 %r0,%r2,%r0# ...high words of the minuend from the subtrahend 26: 7b 0c BRB L5 28: bc 43 41 L3: SUBW2 %r3,%r1 # Subtract the low and the... 2b: 53 04 BCCB L4 # (No borrow? Skip! 2d: 94 40 DECW %r0 # Borrow - take it from the high word) 2f: bc 42 40 L4: SUBW2 %r2,%r0 # ...high words of the minuend from the subtrahend 32: 20 43 L5: POPW %r3 # Restore the saved register 34: 08 RET # Return the absolute value in r0:r1 35: 70 NOP 36: 70 NOP 37: 70 NOP 68K GAS absdif64.s page 1 1 | Да се напише подпрограма, която да връща в регистри D0:D1 абсолютната 2 | стойност (модула) на разликата между двойните думи със знак, подадени в 3 | SP(4) -> D0:D1 и SP(12) -> D2:D3. 4 5 .global absdif64 6 absdif64: 7 0000 4E56 0000 LINK %FP,#0 | Създай стекова рамка 8 0004 48E7 3000 MOVEML %D2-%D3,-(%SP) | GCC изисква D2 и следващите да се съхраняват 9 0008 4CEE 000F 0008 MOVEML 8(%FP),%D0-%D3 | Аргументите в регистри 10 000e 9283 SUBL %D3,%D1 | Извади младшите 11 0010 9182 SUBXL %D2,%D0 | и старшите думи 12 0012 6C04 BGEB L1 | V = N = 0 или V = N = 1: модулът е положителен или 0 13 0014 4481 NEGL %D1 | V = 0, N = 1 или V = 1, N = 0: модулът е отрицателен 14 0016 4080 NEGXL %D0 | - смени му знака 15 0018 4CDF 000C L1: MOVEML (%SP)+,%D2-%D3 16 001c 4E5E UNLK %FP 17 001e 4E75 RTS 18 /* Канонично решение: 19 LINK %FP,#0 | Създай стекова рамка 20 MOVEML %D2-%D3,-(%SP) | GCC изисква D2 и следващите да се съхраняват 21 MOVEML 8(%FP),%D0-%D3 | Аргументите в регистри 22 CMPL %D2,%D0 | Сравни старшите думи 23 BLTB L1 | Умаляемото е по-малко от умалителя - размени ги 24 BGTB L2 | Умаляемото е по-голямо от умалителя - извади ги 25 CMPL %D3,%D1 | Старшите думи са равни - сравни младшите 26 BHSB L2 | Умаляемото е не по-малко от умалителя 27 L1: EXG %D0,%D2 | Умаляемото е по-малко от умалителя: размени старшите 28 EXG %D1,%D3 | и младшите думи на числата 29 L2: SUBL %D3,%D1 | Извади младшите 30 SUBXL %D2,%D0 | и старшите думи на умалителя от умаляемото 31 L3: MOVEML (%SP)+,%D2-%D3 32 UNLK %FP 33 RTS 34 */ x86 NASM absdif64.s 1 ; Да се напише подпрограма, която да връща в регистри EDX:EAX абсолютната 2 ; стойност (модула) на разликата между двойните думи със знак, подадени в 3 ; регистри EDX:EAX и ECX:EBX. 4 5 section .text 6 global absdif64,_absdif64 7 absdif64: 8 _absdif64: 9 00000000 29D8 SUB EAX,EBX ; Извади младшите 10 00000002 19CA SBB EDX,ECX ; и старшите думи 11 00000004 7D07 JGE L1 ; O = S = 0 или O = S = 1: модулът е положителен или 0 12 00000006 F7D8 NEG EAX ; O = 0, S = 1 или O = 1, S = 0: модулът е отрицателен 13 00000008 83D200 ADC EDX,0 ; - смени му знака 14 0000000B F7DA NEG EDX 15 0000000D C3 L1: RET 16 ; Канонично решение: 17 ; CMP EDX,ECX ; Сравни старшите думи 18 ; JL L1 ; Умаляемото е по-малко от умалителя – размени ги 19 ; JG L2 ; Умаляемото е по-голямо от умалителя – извади ги 20 ; CMP EAX,EBX ; Старшите думи са равни – сравни младшите 21 ; JAE L2 ; Умаляемото е не по-малко от умалителя – извади ги 22 ;L1: XCHG EDX,ECX ; Умаляемото е по-малко от умалителя: размени старшите 23 ; XCHG EAX,EBX ; и младшите думи на числата 24 ;L2: SUB EAX,EBX ; Извади младшите 25 ; SBB EDX,ECX ; и старшите думи 26 ; RET ARM GAS absdif64.s page 1 1 // Да се напише подпрограма, която да връща в регистри R1:R0 абсолютната 2 // стойност (модула) на разликата между двойните думи със знак, подадени в 3 // регистри R1:R0 и R3:R2. 4 5 .global absdif64 6 absdif64: 7 0000 020050E0 SUBS R0,R0,R2// Извади младшите 8 0004 0310D1E0 SBCS R1,R1,R3// и старшите думи на умалителя от умаляемото 9 0008 1EFF2FA1 BXGE LR // V = N = 0 или V = N = 1: модулът е положителен или 0 10 000c 000070E2 RSBS R0,R0,#0// V = 0, N = 1 или V = 1, N = 0: модулът е отрицателен 11 0010 0010E1E2 RSC R1,R1,#0// - смени му знака 12 0014 1EFF2FE1 BX LR 13 /* Канонично решение: 14 CMP R1,R3 // Сравни старшите думи 15 BLT L1 // Умаляемото е по-малко от умалителя - извади него 16 BGT L2 // Умаляемото е по-голямо от умалителя - извади от него 17 CMP R0,R2 // Старшите думи са равни - сравни младшите 18 BHS L2 // Умаляемото е не по-малко от умалителя 19 L1: SUBS R0,R2,R0// Умаляемото е по-малко от умалителя: извади младшите 20 SBC R1,R3,R1// и старшите думи на умаляемото от умалителя 21 BX LR 22 L2: SUBS R0,R0,R2// Извади младшите 23 SBC R1,R1,R3// и старшите думи на умалителя от умаляемото 24 BX LR 25 */ ARC GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри r1:r0 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри r1:r0 и r3:r2. 4 5 .global absdif64 6 absdif64: 7 0000 0220 8080 SUB.F r0,r0,r2 # Извади младшите 8 0004 0321 C180 SBC.F r1,r1,r3 # и старшите думи на умалителя от умаляемото 9 0008 E020 CA07 JGE [blink] # V = N = 0 или V = N = 1: модулът е положителен или 0 10 000c 4E20 0080 NEG.F r0,r0 # V = 0, N = 1 или V = 1, N = 0: модулът е отрицателен 11 0010 3379 NEG_S r1,r1 # - смени му знака 12 0012 4321 0100 SBC r1,r1,0 # (извади и заема) 13 0016 E07E J_S [blink] 14 /* Канонично решение: 15 BRLT r1,r3,L1 # Сравни старшите; умаляемото е по-малко от умалителя 16 BRLT r3,r1,L2 # Умаляемото е по-голямо от умалителя - извади от него 17 BRHS r0,r2,L2 # Старшите думи са равни - сравни младшите аналогично 18 L1: SUB.F r0,r2,r0 # Умаляемото е по-малко от умалителя: извади младшите 19 SBC r1,r3,r1 # и старшите думи на умаляемото от умалителя 20 J_S [blink] 21 L2: SUB.F r0,r0,r2 # Извади младшите 22 SBC r1,r1,r3 # и старшите думи на умалителя от умаляемото 23 J_S [blink] 24 */ PPC GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри r3:r4 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри r3:r4 и r5:r6. 4 5 .global absdif64 6 absdif64: 7 0000 7C032800 cmpw r3,r5 # Сравни старшите думи 8 0004 41800010 blt L1 # Умаляемото е по-малко от умалителя - размени ги 9 0008 41810018 bgt L2 # Умаляемото е по-голямо от умалителя - извади ги 10 000c 7C043040 cmplw r4,r6 # Старшите думи са равни - сравни младшите 11 0010 40800010 bge L2 # Умаляемото е не по-малко от умалителя - извади ги 12 0014 7C843010 L1: subfc r4,r4,r6# Умаляемото е по-малко от умалителя: извади младшите 13 0018 7C632910 subfe r3,r3,r5# и старшите думи на умаляемото от умалителя 14 001c 4E800020 blr 15 0020 7C862010 L2: subfc r4,r6,r4# Извади младшите 16 0024 7C651910 subfe r3,r5,r3# и старшите думи на умалителя от умаляемото 17 0028 4E800020 blr SPARC GAS absdif64.s page 1 1 ! Да се напише подпрограма, която да връща в регистри %o0:%o1 абсолютната 2 ! стойност (модула) на разликата между двойните думи със знак, подадени в 3 ! регистри %o0:%o1 и %o2:%o3. 4 5 .global absdif64 6 absdif64: 7 0000 92A2400B subcc %o1,%o3,%o1! Извади младшите и 8 0004 90E2000A subxcc %o0,%o2,%o0! старшите думи на умалителя от умаляемото 9 0008 16800004 bge L1 ! V = N = 0 или V = N = 1: модулът е положителен или 0 10 000c 01000000 nop 11 0010 92A00009 subcc %g0,%o1,%o1! V = 0, N = 1 или V = 1, N = 0: модулът отрицателен 12 0014 90600008 subx %g0,%o0,%o0! - смени му знака 13 0018 81C3E008 L1: retl 14 001c 01000000 nop 15 /* Канонично решение: 16 cmp %o0,%o2 ! Сравни старшите думи 17 bl L1 ! Умаляемото е по-малко от умалителя - извади него 18 nop ! Избегни „Delayed control transfer instruction (DCTI) couple“ 19 bg L2 ! Умаляемото е по-голямо от умалителя - извади от него 20 nop !„Delay slot“: решението е взето, но „cmp“ се изпълнява преди „bg“) 21 cmp %o1,%o3 ! Старшите думи са равни - сравни младшите 22 bcc L2 ! Умаляемото е не по-малко от умалителя 23 nop 24 L1: subcc %o3,%o1,%o1!Умаляемото по-малко от умалителя: извади младшите 25 subx %o2,%o0,%o0! и старшите думи на умаляемото от умалителя 26 retl 27 nop 28 L2: subcc %o1,%o3,%o1! Извади младшите и 29 subx %o0,%o2,%o0! старшите думи на умалителя от умаляемото 30 retl 31 nop 32 */ MIPS GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри $2:$3 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри $4:$5 и $6:$7. 4 5 .ent absdif64 6 .global absdif64 7 absdif64: 8 0000 0086082A 14200007 00000000 BLT $4,$6,L1# Сравни старшите; умаляемото е по-малко от умалителя 9 000c 00C4082A 14200008 00000000 BGT $4,$6,L2# Умаляемото е по-голямо от умалителя - извади ги 10 0018 00A7082B 10200005 00000000 BGEU $5,$7,L2# Старшите думи са равни - сравни младшите аналогично 11 0024 00E5402B L1: SLTU $8,$7,$5# Получи заема 12 0028 00E51823 SUBU $3,$7,$5# Умаляемото е по-малко от умалителя: извади младшите 13 SUBU $2,$6,$4# и старшите думи на умаляемото от умалителя 14 002c 10000004 00C41023 B L3 # as генерира NOP след всеки преход (branch delay slot) 15 0034 00A7402B L2: SLTU $8,$5,$7# Получи заема 16 0038 00A71823 SUBU $3,$5,$7# Извади младшите 17 003c 00861023 SUBU $2,$4,$6# и старшите думи на умалителя от умаляемото 18 L3: SUBU $2,$2,$8# Извади заема 19 0040 03E00008 00481023 JR $31 20 0048 00000000 00000000 .end absdif64 RISC-V GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри a1:a0 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри a1:a0 и a3:a2. 4 5 .global absdif64 6 absdif64: 7 0000 63C6D500 BLT a1,a3,L1 # Сравни старшите; умаляемото е по-малко от умалителя 8 0004 63CBB600 BGT a1,a3,L2 # Умаляемото е по-голямо от умалителя - извади ги 9 0008 6379C500 BGEU a0,a2,L2 # Старшите думи са равни - сравни младшите аналогично 10 000c 3337A600 L1: SLTU a4,a2,a0 # Получи заема 11 0010 3305A640 SUB a0,a2,a0 # Умаляемото е по-малко от умалителя: извади младшите 12 0014 B385B640 SUB a1,a3,a1 # и старшите думи на умаляемото от умалителя 13 0018 29A0 J L3 14 001a 3337C500 L2: SLTU a4,a0,a2 # Получи заема 15 001e 118D SUB a0,a0,a2 # Извади младшите 16 0020 958D SUB a1,a1,a3 # и старшите думи на умалителя от умаляемото 17 0022 998D L3: SUB a1,a1,a4 # Извади заема 18 0024 8280 RET Nios II GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри r3:r2 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри r5:r4 и r7:r6. 4 5 .global absdif64 6 absdif64: 7 0000 1602C029 BLT r5,r7,L1 # Сравни старшите; умаляемото е по-малко от умалителя 8 0004 16054039 BGT r5,r7,L2 # Умаляемото е по-голямо от умалителя - извади ги 9 0008 2E048021 BGEU r4,r6,L2 # Старшите думи са равни - сравни младшите аналогично 10 000c 3A801131 L1: CMPLTU r8,r6,r4 # Получи заема 11 0010 3AC80531 SUB r2,r6,r4 # Умаляемото е по-малко от умалителя: извади младшите 12 0014 3AC84739 SUB r3,r7,r5 # и старшите думи на умаляемото от умалителя 13 0018 06030000 BR L3 14 001c 3A809121 L2: CMPLTU r8,r4,r6 # Получи заема 15 0020 3AC88521 SUB r2,r4,r6 # Извади младшите 16 0024 3AC8C729 SUB r3,r5,r7 # и старшите думи на умалителя от умаляемото 17 0028 3AC8071A L3: SUB r3,r3,r8 # Извади заема 18 002c 3A2800F8 RET Xtensa GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри a3:a2 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри a3:a2 и a5:a4. 4 5 .global absdif64 6 absdif64: 7 0000 572305 BLT a3,a5,L1 # Сравни старшите; умаляемото е по-малко от умалителя 8 0003 37250E BLT a5,a3,L2 # Умаляемото е по-голямо от умалителя - извади ги 9 0006 47B20B BGEU a2,a4,L2 # Старшите думи са равни - сравни младшите аналогично 10 0009 2064C0 L1: SUB a6,a4,a2 # Умаляемото е по-малко от умалителя: извади младшите 11 000c 3035C0 SUB a3,a5,a3 # и старшите думи на умаляемото от умалителя 12 000f 27B40D BGEU a4,a2,L4 # Получи заема 13 0012 060200 J L3 14 0015 4062C0 L2: SUB a6,a2,a4 # Извади младшите 15 0018 5033C0 SUB a3,a3,a5 # и старшите думи на умалителя от умаляемото 16 001b 47B201 BGEU a2,a4,L4 # Получи заема 17 001e 0B33 L3: ADDI a3,a3,-1 # Извади заема 18 0020 2D06 L4: MOV a2,a6 19 0022 0DF0 RET 88K GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри r2:r3 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри r2:r3 и r4:r5. 4 5 .global _absdif64 6 0000 F4C27C04 _absdif64: 7 0004 D8C60004 cmp r6,r2,r4 # Сравни старшите думи 8 0008 D8860006 bb1 lt,r6,L1 # Умаляемото е по-малко от умалителя - извади него 9 000c F4C37C05 bb1 gt,r6,L2 # Умаляемото е по-голямо от умалителя - извади от него 10 0010 D9660004 cmp r6,r3,r5 # Старшите думи са равни - сравни младшите 11 0014 F4656503 bb1 hs,r6,L2 # Умаляемото е не по-малко от умалителя 12 0018 F4446602 L1: subu.co r3,r5,r3 # Умаляемото по-малко от умалителя: извади младшите 13 001c F400C001 subu.ci r2,r4,r2 # и старшите думи на умаляемото от умалителя 14 0020 F4636505 jmp r1 15 0024 F4426604 L2: subu.co r3,r3,r5 # Извади младшите и 16 0028 F400C001 subu.ci r2,r2,r4 # старшите думи на умалителя от умаляемото jmp r1 Or1k GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри R11:R12 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри R3:R4 и R5:R6. 4 5 .global absdif64 6 absdif64: 7 0000 E5832800 L.SFLTS R3,R5 # Сравни ст. думи. Умаляемото по-малко от умалителя? 8 0004 10000005 L.BF L1 # Да, извади него (L.SDGTS променя F, но късно!) 9 0008 E5432800 L.SFGTS R3,R5 # Не, умаляемото по-голямо от умалителя? 10 000c 10000007 L.BF L2 # Да, извади него (L.SFGEU променя F, но " ") 11 0010 E4643000 L.SFGEU R4,R6 # Старшите думи са равни - сравни младшите аналогично 12 0014 10000005 L.BF L2 # L.SUB променя R12, но L.SUB на L2 го променя пак! 13 0018 E1862002 L1: L.SUB R12,R6,R4 # Умаляемото е по-малко от умалителя: извади младшите 14 001c E0630001 L.ADDC R3,R3,R0 # (няма команда L.SUBC; добави преноса към умалителя; 15 0020 44004800 L.JR LR # върни управлението – изпълнява се след L.SUB!) 16 0024 E1651802 L.SUB R11,R5,R3 # и старшите думи на умаляемото от умалителя 17 0028 E1843002 L2: L.SUB R12,R4,R6 # Извади младшите 18 002c E0A50001 L.ADDC R5,R5,R0 # (аналогично на предния случай; 19 0030 44004800 L.JR LR # " " " " " " " ") 20 0034 E1632802 L.SUB R11,R3,R5 # и старшите думи на умалителя от умаляемото Xilinx MicroBlaze GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри R4:R3 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри R6:R5 и R8:R7. 4 5 .global absdif64 6 absdif64: 7 0000 01302815 CMP R9,R8,R6# Сравни старшите думи 8 0004 140049BC BLTI R9,L1 # Умаляемото е по-малко от умалителя - извади него 9 0008 01402615 CMP R9,R6,R8# За R8=-2^31,R6=0 „CMP R9,R8,R6“ -> R9=0! => без BGTI 10 000c 180049BC BLTI R9,L2 # Умаляемото е по-голямо от умалителя - извади от него 11 0010 03282715 CMPU R9,R7,R5# Старшите думи са равни - сравни младшите 12 0014 1000A9BC BGEI R9,L2 # Умаляемото е не по-малко от умалителя 13 0018 00386504 L1: RSUB R3,R5,R7# Умаляемото е по-малко от умалителя: извади младшите.. 14 001c 08000FB6 RTSD R15,8 # (върни резултата в R4:R3; изпълнява се след „RSUBC“!) 15 0020 0040860C RSUBC R4,R6,R8# ...и старшите думи на умаляемото от умалителя 16 0024 00286704 L2: RSUB R3,R7,R5# Извади младшите... 17 0028 08000FB6 RTSD R15,8 # (върни резултата в R4:R3; изпълнява се след „RSUBC“!) 18 002c 0030880C RSUBC R4,R8,R6# ...и старшите думи на умалителя от умаляемото HPPA GAS absdif64.s page 1 1 ; Да се напише подпрограма, която да връща в регистри %R28:%R29 абсолютната 2 ; стойност (модула) на разликата между двойните думи със знак, подадени в 3 ; регистри %R25:%R26 и %R23:%R24. 4 5 .text 6 .global absdif64 7 absdif64: 8 0000 0B1A041D SUB %R26,%R24,%R29 ; Извади младшите 9 0004 0AF9451C SUBB,< %R25,%R23,%R28 ; и старшите думи 10 0008 E840C002 BV,N (%R2) ; Върни модула, освен ако %R25 е бил < от %R23 11 000c 0BA0041D SUB %R0,%R29,%R29 ; Смени знака на модула 12 0010 E840C000 BV (%R2) ; Върни модула (изпълнява се след „SUBB“!) 13 0014 0B80051C SUBB %R0,%R28,%R28 14 ; Канонично решение: 15 ; COMBT,< %R25,%R23,L1; Умаляемото е по-малко от умалителя: извади него 16 ; NOP 17 ; COMBT,< %R23,%R25,L2; Умаляемото по-голямо от умалителя: извади от него 18 ; NOP 19 ; COMBT,<<= %R24,%R26,L2; Старшите думи са равни - сравни младшите 20 ; NOP 21 ;L1: SUB %R24,%R26,%R29; Умаляемото по-малко от умалителя: извади млад- 22 ; BV (%R2) ; (изпълнява се след „SUBB“!) 23 ; SUBB %R23,%R25,%R28; шите и старшите думи на умаляемото от умалителя 24 ;L2: SUB %R26,%R24,%R29; Извади младшите... 25 ; BV (%R2) ; (изпълнява се след „SUBB“!) 26 ; SUBB %R25,%R23,%R28; ...и старшите думи на умалителя от умаляемото Renesas / SuperH SH GAS Little Endian absdif64.s page 1 1 ! Да се напише подпрограма, която да връща в регистри R1:R0 абсолютната 2 ! стойност (модула) на разликата между двойните думи със знак, подадени в 3 ! регистри R5:R4 и R7:R6. 4 5 .global absdif64 6 absdif64: 7 0000 5737 CMP/GT R5,R7 ! Умаляемото по-малко ли е от умалителя? 8 0002 0389 BT L1 ! Да, размени ги 9 0004 7735 CMP/GT R7,R5 ! Не, умаляемото по-голямо ли е от умалителя? 10 0006 0789 BT L2 ! Да, извади от него 11 0008 6234 CMP/HS R6,R4 ! Старшите думи са равни - сравни младшите 12 000a 0589 BT L2 13 000c 0800 L1: CLRT 14 000e 4A36 SUBC R4,R6 ! Умаляемото по-малко от умалителя: извади младшите 15 0010 5A37 SUBC R5,R7 ! и старшите думи на умаляемото от умалителя 16 0012 6360 MOV R6,R0 ! Върни резултата в R1:R0 17 0014 0B00 RTS 18 0016 7361 MOV R7,R1 ! (изпълнява се преди „RTS“!) 19 0018 0800 L2: CLRT 20 001a 6A34 SUBC R6,R4 ! Извади младшите 21 001c 7A35 SUBC R7,R5 ! и старшите думи на умалителя от умаляемото 22 001e 4360 MOV R4,R0 ! Върни резултата в R1:R0 23 0020 0B00 RTS 24 0022 5361 MOV R5,R1 ! (изпълнява се преди „RTS“!) GAS for CRIS absdif64.s page 1 1 ; Да се напише подпрограма, която да връща в регистри R11:R10 абсолютната 2 ; стойност (модула) на разликата между двойните думи със знак, подадени в 3 ; регистри R11:R10 и R13:R12. 4 5 .global absdif64 6 absdif64: 7 0000 ACA6 SUB.D $R12,$R10; Извади младшите и 8 0002 B015 AX ; старшите думи на умалителя от умаляемото 9 0004 ADB6 SUB.D $R13,$R11 10 0006 0CA0 BGE L1 ; V = N = 0 или V = N = 1: модулът е положителен или 0 11 0008 7C86 CLEAR.D $R12 ; изпълнява се преди BGE, но нищо! 12 000a AAC6 SUB.D $R10,$R12; V = 0, N = 1 или V = 1, N = 0: модулът отрицателен - 13 000c 6CA6 MOVE.D $R12,$R10; смени му знака (NEG не променя C, макар че трябва!) 14 000e B015 AX 15 0010 ABB5 NEG.D $R11,$R11 16 0012 F0B9 L1: RET 17 0014 B005 NOP 18 /* Канонично решение: 19 CMP.D $R13,$R11; Сравни старшите думи 20 BLT L1 ; Умаляемото е по-малко от умалителя - размени ги 21 NOP 22 BGT L2 ; Умаляемото е по-голямо от умалителя - извади от него 23 NOP 24 CMP.D $R12,$R10; Старшите думи са равни - сравни младшите 25 BHS L2 ; Умаляемото е не по-малко от умалителя 26 NOP 27 L1: XOR $R10,$R12; Умаляемото по-малко от умалителя: размени 28 XOR $R12,$R10; младшите... 29 XOR $R10,$R12 30 XOR $R11,$R13; ...и старшите им думи 31 XOR $R13,$R11 32 XOR $R11,$R13 33 L2: SUB.D $R12,$R10; Извади младшите и 34 AX ; старшите думи на умалителя от умаляемото 35 SUB.D $R13,$R11 36 RET 37 NOP 38 0016 0000 */ BFIN GAS absdif64.s page 1 1 # Да се напише подпрограма, която да връща в регистри R1:R0 абсолютната 2 # стойност (модула) на разликата между двойните думи със знак, подадени в 3 # регистри R1:R0 и [SP+12]:R2. 4 5 .global _absdif64 6 _absdif64: 7 0000 F3A0 R3 = [SP + 12]; # Старшата дума на умалителя се предава чрез стека 8 0002 9908 CC = R1 < R3; # Сравни старшите думи 9 0004 0518 IF CC JUMP L_1; # Умаляемото е по-малко от умалителя – извади него 10 0006 8B08 CC = R3 < R1; 11 0008 0718 IF CC JUMP L_2; # Умаляемото е по-голямо от умалителя - извади от него 12 000a 020A CC = R2 <= R0 (IU);#Старшите думи са равни - сравни младшите аналогично 13 000c 0518 IF CC JUMP L_2; 14 000e 0252 L_1: R0 = R2 - R0; # Умаляемото е по-малко от умалителя: извади младшите 15 0010 0C03 CC = AC0; # (получи преноса) 16 0012 4B52 R1 = R3 - R1; # и старшите думи на умаляемото от умалителя 17 0014 0420 JUMP L_3; 18 0016 1052 L_2: R0 = R0 - R2; # Извади младшите 19 0018 0C03 CC = AC0; # (получи преноса) 20 001a 5952 R1 = R1 - R3; # и старшите думи на умалителя от умаляемото 21 001c 1802 L_3: CC = !CC; # Съгласно 82-000556-01, стр. 11-3, 22 001e 0202 R2 = CC; # преносът след изваждане е обратен 23 0020 5152 R1 = R1 - R2; # Извади заема 24 0022 1000 RTS; # Върни управлението Hexagon GAS absdif64.s page 1 1 // Да се напише подпрограма, която да връща в регистри R1:R0 абсолютната 2 // стойност (модула) на разликата между двойните думи със знак, подадени в 3 // регистри R1:R0 и R3:R2. 4 5 .global absdif64 6 absdif64: 7 0000 40C082D2 P0 = CMP.GT(R3:2,R1:0) // Умалителят по-голям ли е от умаляемото? 8 0004 06C0005C IF (P0) JUMP L1 // Да – извади умаляемото от умалителя 9 { R1:0 = SUB(R1:0,R3:2) // Не – извади умалителя от умаляемото 10 0008 E04022D3 00C09F52 JUMPR LR } 11 L1: { R1:0 = SUB(R3:2,R1:0) 12 0010 E04220D3 00C09F52 JUMPR LR } S/390 GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър 2 цялата част на 2 # квадратния корен на числото в регистри 2:3, която част е равна на броя 3 # последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 A748FFFF LHI 4,-1 # Задай начална стойност -1 на 33-битовия умалител 8 0004 1854 LR 5,4 9 0006 1700 XR 0,0 # Подготви събираемите за цикъла 10 0008 A7180002 LHI 1,2 11 000c 1E51 L1: ALR 5,1 # Получи следващото нечетно число 12 000e B9980040 ALCR 4,0 13 0012 1F35 SLR 3,5 # Извади младшите думи 14 0014 B9990024 SLBR 2,4 # Извади старшите думи 15 0018 A734FFFA BRC 3,L1 # Ако още няма пренос (0 или не), следваща итерация 16 001c 8C400001 SRDL 4,1 # Раздели на 2 последното нечетно число 17 0020 1825 LR 2,5 # Рег. 2 = броя извадени последователни нечетни числа 18 0022 07FE BR 14 ==> id32/sqroot.s <== 1 * Return in register 0 the integer part of the square root of the double word 2 * number in 7(0) -> 0:1, which part is equal to the number of the consecutive 3 * odd numbers that can be subtracted from that number. 4 5 entry sqroot64 00000000d 6 sqroot64 equ * 00000d 5807 0000 7 l 0,0(7) High word of the number 00004d 5817 0004 8 l 1,4(7) Low word " " " 00008d 2521 9 lcs 2,1 Initialise the 33-bit subtrahend with -1 0000Ad 0832 10 lr 3,2 0000Cd 2632 11 L1 ais 3,2 Get the next odd number 0000Ed 2382 00000012d 12 bncs L2 No carry? Skip! 00010d 2621 13 ais 2,1 Carry - add it to the high word 00012d 0B13 14 L2 sr 1,3 Subtract the low words 00014d 2383 0000001Ad 15 bncs L3 No borrow? Skip! 00016d 2701 16 sis 0,1 Borrow - subtract it from the high minuend word 00018d 2183 0000001Ed 17 bcs L4 Borrow again? End the loop! 0001Ad 0B02 18 L3 sr 0,2 Subtract the high words 0001Cd 2288 0000000Cd 19 bncs L1 No carry yet? Continue the loop! 0001Ed 1031 20 L4 srls 3,1 Divide the subtrahend to 2 00020d 0803 21 lr 0,3 Return value must be in register 0 00022d ED20 001F 22 sll 2,31(0) Move the lowmost bit to highmost one 00026d 0602 23 or 0,2 \ Register 0 = the number of the subtracted odd numbers 00028d 030F 24 br 15 \Reg.0: no indexing (29-405R00, p.1-6, 29-428R06, p.1-7) VAX GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 цялата част на 2 # квадратния корен на числото в AP(4):AP(8) -> R1:R0, която част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global _sqroot64 6 _sqroot64: 7 0000 0C00 .word 0xC # R2-R3 8 0002 7DAC0450 MOVQ 4(AP),R0# R1 = старшата дума, R0 = младшата 9 0006 D08FFFFF FFFF53 MOVL $-1,R3 # Задай начална стойност -1 на 33-битовия умалител 10 000d D05352 MOVL R3,R2 11 0010 C00252 L1: ADDL2 $2,R2 # Получи следващото нечетно число 12 0013 D80053 ADWC $0,R3 13 0016 C25250 SUBL2 R2,R0 # Извади младшите думи 14 0019 D95351 SBWC R3,R1 # Извади старшите думи 15 001c 1EF2 BGEQU L1 # Ако още няма пренос, следваща итерация 16 001e 798FFF52 50 ASHQ $-1,R2,R0# R0 = броя извадени последователни нечетни числа 17 0023 04 RET ==> we32k/sqroot64.s <== # Return in the r0 register the integer part of the square root of the number # in ap(0):ap(4) -> r0:r1, which part is equal to the number of the consecutive # odd numbers that can be subtracted from that number. section .text .globl sqroot64 sqroot64() sqroot64: 0: a0 43 PUSHW %r3 # "AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 40 MOVW 0(%ap),%r0 # Programming Manual", pp. 6-13, 6-14 5: 84 74 41 MOVW 4(%ap),%r1 # r0 = high word, r1 = low word 8: 84 ff 42 MOVW &-1,%r2 # Initialise the 33-bit subtrahend with -1 b: 84 42 43 MOVW %r2,%r3 e: 9c 02 43 L1: ADDW2 &2,%r3 # Get the next odd number 11: 53 04 BCCB L2 # No carry? Skip! 13: 90 42 INCW %r2 # Carry - add it to the high word 15: bc 43 41 L2: SUBW2 %r3,%r1 # Subtract the low words 18: 53 07 BCCB L3 # No borrow? Skip! 1a: bc 01 40 SUBW2 &1,%r0 # Borrow - subtract it from the high minuend word 1d: 5b 07 BCSB L4 # Borrow again? End the loop! 1f: bc 42 40 L3: SUBW2 %r2,%r0 # Subtract the high words 22: 53 ec BCCB L1 # No carry yet? Continue the loop! 24: cc 1e 01 43 40 L4: EXTFW &30,&1,%r3,%r0# Divide the subtrahend to 2 29: c8 00 1f 42 40 INSFW &0,&31,%r2,%r0# r0 = the number of the subtracted odd numbers 2e: 20 43 POPW %r3 # Restore the saved register and return 30: 08 RET 31: 70 NOP 32: 70 NOP 33: 70 NOP 68K GAS sqroot64.s page 1 1 | Да се напише подпрограма, която да връща в регистър D0 цялата част на 2 | квадратния корен на числото в SP(4):SP(8) -> D0:D1, която част е равна на 3 | броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 4CEF 0003 0004 MOVEML 4(%SP),%D0-%D1 | D0 = старшата дума, D1 = младшата 8 0006 48E7 3800 MOVEML %D2-%D4,-(%SP) | GCC изисква D2 и следващите да се съхраняват 9 000a 74FF MOVEQ #-1,%D2 | Задай начална стойност -1 на 33-битовия умалител 10 000c 2602 MOVEL %D2,%D3 11 000e 4284 CLRL %D4 12 0010 5483 L1: ADDQL #2,%D3 | Получи следващото нечетно число 13 0012 D584 ADDXL %D4,%D2 14 0014 9283 SUBL %D3,%D1 | Извади младшите думи 15 0016 9182 SUBXL %D2,%D0 | Извади старшите думи 16 0018 64F6 BHSB L1 | Ако още няма пренос, следваща итерация 17 001a E9C3 001F BFEXTU %D3{0:31},%D0| Раздели умалителя на 2 18 001e EFC0 2001 BFINS %D2,%D0{0:1} | D0 = броя извадени последователни нечетни числа 19 0022 4CDF 001C MOVEML (%SP)+,%D2-%D4 20 0026 4E75 RTS x86 NASM sqroot64.s 1 ; Да се напише подпрограма, която да връща в регистър EAX цялата част на 2 ; квадратния корен на числото в регистрите EDX:EAX, която цяла част е равна на 3 ; броя последователни нечетни числа, които могат да се извадят от това число. 4 5 section .text 6 global sqroot64,_sqroot64; в GCC декларирай с __attribute__((regparm(3))) 7 sqroot64: 8 _sqroot64: 9 00000000 53 PUSH EBX ; GCC изисква EBX да се съхранява 10 00000001 B9FFFFFFFF MOV ECX,-1 ; Задай начална стойност -1 на 33-битовия умалител 11 00000006 89CB MOV EBX,ECX ; в EBX:ECX 12 00000008 83C102 L1: ADD ECX,2 ; Получи следващото нечетно число 13 0000000B 83D300 ADC EBX,0 14 0000000E 29C8 SUB EAX,ECX ; Извади младшите думи 15 00000010 19DA SBB EDX,EBX ; Извади старшите думи 16 00000012 73F4 JNC L1 ; Ако още няма пренос, направи следващата итерация 17 00000014 0FACD901 SHRD ECX,EBX,1;Раздели така получения умалител на 2 18 00000018 91 XCHG EAX,ECX ; EAX = броя извадени последователни нечетни числа 19 00000019 5B POP EBX 20 0000001A C3 RET ARM GAS sqroot64.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 цялата част на 2 // квадратния корен на числото в регистрите R1:R0, която цяла част е равна на 3 // броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 0030E0E3 MOV R3,#-1 // Задай начална стойност -1 на 33-битовия умалител 8 0004 0320A0E1 MOV R2,R3 9 0008 022092E2 L1: ADDS R2,R2,#2// Получи следващото нечетно число 10 000c 0030A3E2 ADC R3,R3,#0 11 0010 020050E0 SUBS R0,R0,R2// Извади младшите думи 12 0014 0310D1E0 SBCS R1,R1,R3// Извади старшите думи 13 0018 FAFFFF2A BHS L1 // Ако още няма пренос (има заем), следваща итерация 14 001c A330B0E1 MOVS R3,R3,LSR #1//Раздели така получения умалител на 2 15 0020 6200A0E1 MOV R0,R2,RRX//R0 = броя извадени последователни нечетни числа 16 0024 1EFF2FE1 BX LR ARC GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r0 цялата част на 2 # квадратния корен на числото в регистрите r1:r0, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 6C77 MOV_S r3,-1 # Задай начална стойност -1 на 33-битовия умалител 8 0002 6042 MOV_S r2,r3 9 0004 4022 8280 L1: ADD.F r2,r2,2 # Получи следващото нечетно число 10 0008 4123 0300 ADC r3,r3,0 11 000c 0220 8080 SUB.F r0,r0,r2 # Извади младшите думи 12 0010 0321 C180 SBC.F r1,r1,r3 # Извади старшите думи 13 0014 78F7 BHS_S L1 # Ако още няма пренос (има заем), следваща итерация 14 0016 2F23 C280 LSR.F r3,r3 # Раздели така получения умалител на 2 15 001a 2F20 8400 RRC r0,r2 # r0 = броя извадени последователни нечетни числа 16 001e E07E J_S [blink] PPC GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r3 цялата част на 2 # квадратния корен на числото в регистрите r3:r4, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 38A0FFFF li r5,-1 # Задай начална стойност -1 на 33-битовия умалител 8 0004 7CA62B78 mr r6,r5 9 0008 30C60002 L1: addic r6,r6,2 # Получи следващото нечетно число 10 000c 7CA50194 addze r5,r5 11 0010 7C862010 subfc r4,r6,r4# Извади младшите думи 12 0014 7C651910 subfe r3,r5,r3# Извади старшите думи 13 0018 7CE73911 subfe. r7,r7,r7# Още ли няма пренос (има заем)? 14 001c 4182FFEC beq+ L1 # Да, следваща итерация 15 0020 54C3F87E srwi r3,r6,1 # Не, раздели така получения умалител на 2 16 0024 50A3F800 rlwimi r3,r5,31,0,0# Копирай най-младшия бит на мястото на най-старшия 17 0028 4E800020 blr # r3 = броя извадени последователни нечетни числа SPARC GAS sqroot64.s page 1 1 ! Да се напише подпрограма, която да връща в регистър %o0 цялата част на 2 ! квадратния корен на числото в регистрите %o0:%o1, която цяла част е равна на 3 ! броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 94103FFF mov -1,%o2 ! Задай начална стойност -1 на 33-битовия умалител 8 0004 9610000A mov %o2,%o3 9 0008 9682E002 L1: addcc %o3,2,%o3 ! Получи следващото нечетно число 10 000c 9442A000 addx %o2,0,%o2 11 0010 92A2400B subcc %o1,%o3,%o1! Извади младшите думи 12 0014 90E2000A subxcc %o0,%o2,%o0! Извади старшите думи 13 0018 1ABFFFFC bcc L1 ! Ако още няма пренос (заем), следваща итерация 14 001c 01000000 nop 15 0020 9132E001 srl %o3,1,%o0 ! Раздели така получения умалител на 2 16 0024 952AA01F sll %o2,31,%o2 ! Копирай най-младшия бит на мястото на най-старшия 17 0028 81C3E008 retl ! Изпълнява се след „or“! 18 002c 9012000A or %o0,%o2,%o0! %o0 = броя извадени последователни нечетни числа MIPS GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър $2 цялата част на 2 # квадратния корен на числото в регистрите $4:$5, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .ent sqroot64 6 .global sqroot64 7 sqroot64: 8 0000 2406FFFF LI $6,-1 # Задай начална стойност -1 на 33-битовия умалител 9 0004 00C03821 MOVE $7,$6 10 0008 24E70002 L1: ADDIU $7,$7,2 # Получи следващото нечетно число - в младшата 11 000c 2CE80002 SLTIU $8,$7,2 # (получи преноса) 12 0010 00C83021 ADDU $6,$6,$8# и в старшата дума 13 0014 00A7402B SLTU $8,$5,$7# Получи заема за младшите думи 14 0018 00A72823 SUBU $5,$5,$7# Извади ги 15 001c 0086082B 14200007 00000000 BLTU $4,$6,L2# Ако ще има заем за старшите думи, край на цикъла 16 0028 00862023 SUBU $4,$4,$6# Извади старшите думи 17 002c 0088082B 14200003 00000000 BLTU $4,$8,L2# Може ли да се извади и заемът за младшите думи? 18 SUBU $4,$4,$8# Да, извади го 19 0038 1000FFF3 00882023 B L1 # и продължи цикъла 20 0040 00071042 L2: SRL $2,$7,1 # Не, раздели така получения умалител на 2 21 INS $2,$6,31,1# Копирай най-младшия бит на мястото на най-старшия 22 0044 03E00008 7CC2FFC4 JR $31 # $2 = броя извадени последователни нечетни числа 23 004c 00000000 .end sqroot64 RISC-V GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър a0 цялата част на 2 # квадратния корен на числото в регистрите a1:a0, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 FD56 LI a3,-1 # Задай начална стойност -1 на 33-битовия умалител 8 0002 3686 MV a2,a3 9 0004 0906 L1: ADDI a2,a2,2 # Получи следващото нечетно число - в младшата 10 0006 13372600 SLTIU a4,a2,2 # (получи преноса) 11 000a BA96 ADD a3,a3,a4 # и в старшата дума 12 000c 3337C500 SLTU a4,a0,a2 # Получи заема за младшите думи 13 0010 118D SUB a0,a0,a2 # Извади ги 14 0012 63E7D500 BLTU a1,a3,L2 # Ако ще има заем за старшите думи, край на цикъла 15 0016 958D SUB a1,a1,a3 # Извади старшите думи 16 0018 63E4E500 BLTU a1,a4,L2 # Може ли да се извади и заемът за младшите думи? 17 001c 998D SUB a1,a1,a4 # Да, извади го 18 001e DDB7 J L1 # и продължи цикъла 19 0020 13551600 L2: SRLI a0,a2,1 # Не, раздели така получения умалител на 2 20 0024 FE06 SLLI a3,a3,31 # Копирай най-младшия бит на мястото на най-старшия 21 0026 558D OR a0,a0,a3 22 0028 8280 RET # a0 = броя извадени последователни нечетни числа Nios II GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 цялата част на 2 # квадратния корен на числото в регистрите r5:r4, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 C4FFFF01 MOVI r7,-1 # Задай начална стойност -1 на 33-битовия умалител 8 0004 3A880D38 MOV r6,r7 9 0008 84008031 L1: ADDI r6,r6,2 # Получи следващото нечетно число - в младшата 10 000c B0000032 CMPLTUI r8,r6,2 # (получи преноса) 11 0010 3A880F3A ADD r7,r7,r8# и в старшата дума 12 0014 3A809121 CMPLTU r8,r4,r6# Получи заема за младшите думи 13 0018 3AC88921 SUB r4,r4,r6# Извади ги 14 001c 3604C029 BLTU r5,r7,L2# Ако ще има заем за старшите думи, край на цикъла 15 0020 3AC8CB29 SUB r5,r5,r7# Извади старшите думи 16 0024 3602002A BLTU r5,r8,L2# Може ли да се извади и заемът за младшите думи? 17 0028 3AC80B2A SUB r5,r5,r8# Да, извади го 18 002c 06F63F00 BR L1 # и продължи цикъла 19 0030 7AD00430 L2: SRLI r2,r6,1 # Не, раздели така получения умалител на 2 20 0034 FA970E38 SLLI r7,r7,31# Копирай най-младшия бит на мястото на най-старшия 21 0038 3AB0C411 OR r2,r2,r7 22 003c 3A2800F8 RET # r2 = броя извадени последователни нечетни числа Xtensa GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър a2 цялата част на 2 # квадратния корен на числото в регистрите a3:a2, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 7CF5 MOVI a5,-1 # Задай начална стойност -1 на 33-битовия умалител 8 0002 4D05 MOV a4,a5 9 0004 42C402 L1: ADDI a4,a4,2 # Получи следващото нечетно число в младшата дума 10 0007 F62402 BGEUI a4,2,L2 # Има ли пренос? 11 000a 52C501 ADDI a5,a5,1 # Да, добави го към старшата дума 12 000d 47B203 L2: BGEU a2,a4,L3 # Ще има ли заем за младшите думи? 13 0010 8CC3 BEQZ a3,L4 # Да, и ако старшата дума е вече 0, край на цикъла 14 0012 0B33 ADDI a3,a3,-1 # Извади заема от старшата дума на умаляемото 15 0014 4022C0 L3: SUB a2,a2,a4 # Извади младшите думи 16 0017 573305 BLTU a3,a5,L4 # Ако ще има заем за старшите думи, край на цикъла 17 001a 5033C0 SUB a3,a3,a5 # Извади старшите думи 18 001d C6F8FF J L1 # Продължи цикъла 19 0020 0C12 L4: MOVI a2,1 # Не, раздели така получения умалител на 2 20 0022 000240 SSR a2 21 0025 402581 SRC a2,a5,a4 22 0028 0DF0 RET # a2 = броя извадени последователни нечетни числа 88K GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 цялата част на 2 # квадратния корен на числото в регистрите r2:r3, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global _sqroot64 6 0000 64800001 _sqroot64: 7 0004 F4A45800 subu r4,r0,1 # Задай начална стойност -1 на 33-битовия умалител 8 0008 58E00002 or r5,r4,r0 9 000c F4A56107 or r7,r0,2 # Подготви събираемото 10 0010 F4846200 L1: addu.co r5,r5,r7 # Получи следващото нечетно число 11 0014 F4636505 addu.ci r4,r4,r0 12 0018 F4426704 subu.co r3,r3,r5 # Извади младшите думи 13 001c F4C66606 subu.cio r2,r2,r4 # Извади старшите думи 14 0020 E846FFFB subu.ci r6,r6,r6 # Още ли няма пренос? 15 0024 F0459801 bcnd eq0,r6,L1 # Да, следваща итерация 16 0028 F084A801 extu r2,r5,0<1> # Не, раздели така получения умалител на 2 17 002c F4425804 rot r4,r4,<1> # Копирай най-младшия бит на мястото на най-старшия 18 0030 F400C001 or r2,r2,r4 jmp r1 # r2 = броя извадени последователни нечетни числа Or1k GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R11 цялата част на 2 # квадратния корен на числото в регистрите R3:R4, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 9CA0FFFF L.ADDI R5,R0,-1 # Задай начална стойност -1 на 33-битовия умалител 8 0004 E0C50004 L.OR R6,R5,R0 9 0008 9CC60002 L1: L.ADDI R6,R6,2 # Получи следващото нечетно число - в младшата 10 000c E0A50001 L.ADDC R5,R5,R0 # и в старшата дума 11 0010 E0843002 L.SUB R4,R4,R6 # Извади младшите думи 12 0014 E0E50001 L.ADDC R7,R5,R0 # Получи сбор от старшата дума на умалителя и преноса 13 0018 E0633802 L.SUB R3,R3,R7 # Извади старшите думи 14 001c E0E00001 L.ADDC R7,R0,R0 # Копирай преноса в регистър 15 0020 E4270000 L.SFNE R7,R0 # Има ли пренос? 16 0024 0FFFFFF9 L.BNF L1 # Не, продължи цикъла (изп.се след „L.SRLI“, но нищо) 17 0028 B9660041 L2: L.SRLI R11,R6,1 # Да, раздели така получения умалител на 2 18 002c B8A5001F L.SLLI R5,R5,31 # Копирай най-младшия бит на мястото на най-старшия 19 0030 44004800 L.JR LR # Изпълнява се след „L.OR“! 20 0034 E16B2804 L.OR R11,R11,R5# R11 = броя извадени последователни нечетни числа Xilinx MicroBlaze GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R3 цялата част на 2 # квадратния корен на числото в регистрите R6:R5, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 FFFFE020 ADDI R7,R0,-1# Задай начална стойност -1 на 33-битовия умалител 8 0004 00000781 OR R8,R7,R0 9 0008 0200E720 L1: ADDI R7,R7,2 # Получи следващото нечетно число 10 000c 00000809 ADDC R8,R8,R0 11 0010 0028A704 RSUB R5,R7,R5# Извади младшите думи 12 0014 0030C80C RSUBC R6,R8,R6# Извади старшите думи 13 0018 0048290D RSUBC R9,R9,R9# Още ли няма пренос (има заем)? 14 001c ECFF09BC BEQI R9,L1 # Да, следваща итерация 15 0020 41000891 SRL R8,R8 # Не, раздели така получения умалител на 2 16 0024 08000FB6 RTSD R15,8 # Върни резултата в R3 (изпълнява се след „SRC“!) 17 0028 21006790 SRC R3,R7 # Копирай най-младшия бит на мястото на най-старшия HPPA GAS sqroot64.s page 1 1 ; Да се напише подпрограма, която да връща в регистър %R28 цялата част на 2 ; квадратния корен на числото в регистрите %R25:%R26, която цяла част е равна 3 ; на броя последователни нечетни числа, които могат да се извадят от това число 4 5 .text 6 .global sqroot64 7 sqroot64: 8 0000 34173FFF LDI -1,%R23 ; Задай начална стойност -1 на 33-битовия умалител 9 0004 08170258 COPY %R23,%R24 10 0008 B7180004 L1: ADDI 2,%R24,%R24 ; Получи следващото нечетно число 11 000c 0AE00717 ADDC %R0,%R23,%R23 12 0010 0B1A041A SUB %R26,%R24,%R26 ; Извади младшите думи 13 0014 0AF98519 SUBB,<< %R25,%R23,%R25 ; Извади старшите думи и анулирай „B“ при заем 14 0018 E81F1FD7 B,N L1 ; Следваща итерация (командата „BV“ се анулира) 15 001c E840C000 BV (%R2) ; %R28 = броя извадени последователни нечетни числа 16 0020 D3170BDC SHD %R23,%R24,1,%R28; Раздели умалителя на 2 (изп. се преди „BV“!) 16 00000000 Renesas / SuperH SH GAS Little Endian sqroot64.s page 1 1 ! Да се напише подпрограма, която да връща в регистър R0 цялата част на 2 ! квадратния корен на числото в регистрите R5:R4, която цяла част е равна на 3 ! броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 FFE0 MOV #-1,R0 ! Задай начална стойност -1 на 33-битовия умалител 8 0002 0361 MOV R0,R1 ! в R1:R0 9 0004 02E2 MOV #2,R2 ! Подготви младшата 10 0006 00E3 MOV #0,R3 ! и старшата дума за събирането 11 0008 0800 L1: CLRT 12 000a 2E30 ADDC R2,R0 ! Получи следващото нечетно число 13 000c 3E31 ADDC R3,R1 14 000e 0800 CLRT 15 0010 0A34 SUBC R0,R4 ! Извади младшите думи 16 0012 1A35 SUBC R1,R5 ! Извади старшите думи 17 0014 F88B BF L1 ! Ако още няма пренос, направи следващата итерация 18 0016 0141 SHLR R1 ! Раздели така получения умалител на 2 19 0018 0B00 RTS ! (Изпълнява се след „ROTCR“!) 20 001a 2540 ROTCR R0 ! R0 = броя извадени последователни нечетни числа GAS for CRIS sqroot64.s page 1 1 ; Да се напише подпрограма, която да връща в регистър R10 цялата част на 2 ; квадратния корен на числото в регистрите R11:R10, която цяла част е равна на 3 ; броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 0000 7FD2 MOVEQ -1,$R13 ; Задай начална стойност -1 на 33-битовия умалител 8 0002 6DC6 MOVE.D $R13,$R12 9 0004 02C2 L1: ADDQ 2,$R12 ; Получи следващото нечетно число 10 0006 B015 AX 11 0008 00D2 ADDQ 0,$R13 12 000a ACA6 SUB.D $R12,$R10 ; Извади младшите думи 13 000c B015 AX 14 000e ADB6 SUB.D $R13,$R11 ; Извади старшите думи 15 0010 F500 BCC L1 ; Ако още няма пренос (заем), следваща итерация 16 0012 B005 NOP 17 0014 6CA6 MOVE.D $R12,$R10 ; Резултатът ще бъде в R10 (изпълн. се преди „BCC“!) 18 0016 E1A3 LSRQ 1,$R10 ; Раздели така получения умалител на 2 19 0018 DFD3 LSLQ 31,$R13 ; Копирай най-младшия бит на мястото на най-старшия 20 001a F0B9 RET ; Изпълнява се след „OR“! 21 001c 6DA70000 OR.D $R13,$R10 ; R10 = броя извадени последователни нечетни числа BFIN GAS sqroot64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 цялата част на 2 # квадратния корен на числото в регистрите R1:R0, която цяла част е равна на 3 # броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global _sqroot64 6 _sqroot64: 7 0000 FB63 R3 = -1 (X); # Задай начална стойност -1 на 33-битовия умалител 8 0002 1330 R2 = R3; 9 0004 1264 L_1: R2 += 2; # Получи следващото нечетно число в младшата дума 10 0006 0C03 CC = AC0; # Има ли пренос? 11 0008 0210 IF !CC JUMP L_2; # Не, прескочи 12 000a 0B64 R3 += 1; # Да, добави го към старшата дума 13 000c 9009 L_2: CC = R0 < R2 (IU);# Ще има ли заем за младшите думи? 14 000e 0410 IF !CC JUMP L_3; # Не, прескочи 15 0010 0902 CC = R1; # Да, нула ли е старшата дума? 16 0012 0710 IF !CC JUMP L_4; # Да, край на цикъла 17 0014 F967 R1 += -1; # Извади заема от старшата дума на умаляемото 18 0016 1052 L_3: R0 = R0 - R2; # Извади младшите думи 19 0018 9909 CC = R1 < R3 (IU);# Ще има ли заем за старшите думи? 20 001a 0318 IF CC JUMP L_4; # Да, край на цикъла 21 001c 5952 R1 = R1 - R3; # Не, извади старшите думи 22 001e F32F JUMP L_1; # и продължи цикъла 23 0020 82C6FBC7 L_4: R3 = ROT R3 BY -1;# Раздели така получения умалител на 2 24 0024 82C6FAC1 R0 = ROT R2 BY -1; 25 0028 10000000 RTS; # R0 = броя извадени последователни нечетни числа Hexagon GAS sqroot64.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 цялата част на 2 // квадратния корен на числото в регистрите R1:R0, която цяла част е равна на 3 // броя последователни нечетни числа, които могат да се извадят от това число. 4 5 .global sqroot64 6 sqroot64: 7 { R3:2 = #-1 // Задай начална стойност -1 на 33-битовия умалител 8 R5:4 = #2 // Стъпка на аритметичната прогресия на нечетните числа 9 0000 E27F7F7C 0440017C 00C000F2 P0 = CMP.EQ(R0,R0)}// Нулирай заема на входа на изваждането (P0 = 1) 10 000c E2C402D3 L1: R3:2 = ADD(R3:2,R5:4)// Получи следващото нечетно число и го извади 11 0010 00C2E0C2 R1:0 = SUB(R1:0,R3:2,P0):CARRY // от остатъчната подкоренова величина 12 0014 FCE0DF5C IF (P0) JUMP L1 // Ако още има пренос (няма заем), следваща итерация 13 { R1:0 = LSR(R3:2,#1) // Раздели така получения умалител на 2 14 0018 20410280 00C09F52 JUMPR LR } // R0 = броя извадени последователни нечетни числа S/390 GAS lcmult.s page 1 1 # Върни в регистър 2 най-малкото общо кратно (НОК) на числата в регисри 2 и 3 2 3 .global lcmult 4 lcmult: 5 0000 181E LR 1,14 # Съхрани адреса на връщане, защото BRAS ще го промени! 6 0002 1852 LR 5,2 7 0004 B9960043 MLR 4,3 # 4:5 = A * B 8 0008 A7E50006 BRAS 14,GCD # намери НОД(A, B) 9 000c B9970042 DLR 4,2 # регистър 5 = A * B / НОД(A, B) = НОК 10 0010 1825 LR 2,5 # НОК трябва да се върне в регистър 2 11 0012 07F1 BR 1 # Върни се в извикващата програма 12 GCD: 13 .include "gcdivis.s" 1 # Върни в регистър 2 най-големия общ делител на числата в регистри 2 и 3 2 # (алгоритъм - Евклид от Александрия). 3 4 0014 1802 LR 0,2 5 0016 1603 OR 0,3 #unsigned gcd(unsigned a, unsigned b) 6 0018 A7740004 JNZ L1 #{ 7 001c A7280001 LHI 2,1 #____ if (a == 0 && b == 0) 8 0020 1233 L1: LTR 3,3 # \__ return 1; 9 0022 078E BER 14 #___ if (b == 0) 10 0024 1222 LTR 2,2 #__ \___ return a; 11 0026 A7740003 JNE L2 # \ 12 002a 1823 LR 2,3 # \__ if (a != 0) 13 002c 1523 L2: CLR 2,3 # while (a != b) 14 002e A7B40005 JNL L3 # if (a < b) 15 0032 1F32 SLR 3,2 # b -= a; 16 0034 A7F4FFFC J L2 # else 17 0038 078E L3: BER 14 # a -= b; 18 003a 1F23 SLR 2,3 # return b; 19 003c A7F4FFF8 J L2 #} ==> id32/lcmult.s <== 1 * Return in register 0 the least common multiple (LCM) of the numbers in 2 * 7(0) -> reg. 0 and 7(4) -> reg. 1 (they must be up to 31 bits due to the 3 * limits of the multiplication and division instructions; the ID32 doesn't 4 * have instrctions for unsigned multiplication and division). 5 6 entry lcmult,GCD 00000000d 7 lcmult equ * 00000d 084F 8 lr 4,15 Save link register 15 because "bal" will change it 00002d 5807 0000 9 l 0,0(7) A 00006d 5817 0004 10 l 1,4(7) B 0000Ad 0831 11 lr 3,1 B 0000Cd 1C20 12 mr 2,0 2:3 = A * B 0000Ed 41F0 8006 00000018d 13 bal 15,GCD Find the greatest common divisor GCD(A, B) 00012d 1D20 14 dr 2,0 Reg. 3 = A * B / GCD(A, B) = LCM 00014d 0803 15 lr 0,3 Will be returned in register 0 00016d 0304 16 br 4 Return to the calling function 17 18 * Return in reg.0 the greatest common divisor of the numbers in registers 0 19 * and 1 (algorithm - Euclid of Alexandria, x86 implementation: Paul Hsieh). 20 00000018d 21 GCD equ * int gcd(a, b) 00018d C700 FFFF 22 xi 0,-1(0) negate int a, b; 0001Cd 2601 23 ais 0,1 { 0001Ed 233A 00000032d 24 bes L3 if (a == 0 && b == 0) return 1; 00020d C700 FFFF 25 L1 xi 0,-1(0) " " __ 00024d 2601 26 ais 0,1 \ 00026d 0701 27 xr 0,1 exchange \ 00028d 0710 28 xr 1,0 0 and 1 \ 0002Ad 0701 29 xr 0,1 \ if (b == 0) return a; 0002Cd 0B01 30 L2 sr 0,1 \ if (a != 0) 0002Ed 2021 0000002Cd 31 bps L2 \__ while (a != b) 00030d 2018 00000020d 32 bms L1 ____ / if (a < b) 00032d 0A01 33 L3 ar 0,1 X b -= a; 00034d 023F 34 bnzr 15 ___/ \_ else a -= b; 00036d 2601 35 ais 0,1 return b; 00038d 030F 36 br 15 } VAX GAS lcmult.s page 1 1 # Върни в R0 най-малкото общо кратно (НОК) на числата в AP(4) -> R0 и 2 # AP(8) -> R1 (те трябва да са до 31 бита поради ограничението на командите 3 # EMUL и EDIV; VAX няма команди за дълго беззнаково умножение и делене). 4 5 .global _lcmult 6 _lcmult: 7 0000 1C00 .word 0x1C # R2-R4 8 0002 7DAC0450 MOVQ 4(AP),R0 # R0 = A, R1 = B 9 0006 7A505100 53 EMUL R0,R1,$0,R3 # R4:R3 = A * B 10 000b 1006 BSBB GCD # намери НОД(A, B) 11 000d 7B505350 51 EDIV R0,R3,R0,R1 # R0 = A * B / НОД(A, B) = НОК 12 0012 04 RET # Върни се в извикващата програма 13 GCD: 14 .include "gcdivis.s" 1 # Върни в R0 най-големия общ делител на числата в R0 и R1 2 # (алгоритъм - Евклид от Александрия, реализация за x86: Paul Hsieh). 3 4 0013 CE5050 MNEGL R0,R0 # unsigned gcd(unsigned a, unsigned b) 5 0016 130D BEQL L3 # { 6 0018 CE5052 L1: MNEGL R0,R2 # if (a == 0 && b == 0) return 1; 7 001b 7D5150 MOVQ R1,R0 #\ if (b == 0) return a; 8 001e C25150 L2: SUBL2 R1,R0 # \ if (a != 0) 9 0021 1AFB BGTRU L2 # \_ while (a != b) 10 0023 1FF3 BLSSU L1 # if (a < b) 11 0025 C05150 L3: ADDL2 R1,R0 #\ b -= a; 12 0028 1202 BNEQ L4 # \_ else a -= b; 13 002a D650 INCL R0 # return b; 14 002c 05 L4: RSB # } ==> we32k/lcmult.S <== /* Return in %r0 the least common multiple (LCM) of the numbers in ap(0) -> r0 * and ap(4) -> r1 (they must be up to 31 bits due to the limits of the MULW and * DIVW instructions; the WE32K does't have instrctions for long or unsigned * multiplication and division). */ section .text .globl lcmult lcmult() lcmult: 0: a0 43 PUSHW %r3 # "AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 40 MOVW 0(%ap),%r0 # Programming Manual", pp. 6-13, 6-14 5: 84 74 41 MOVW 4(%ap),%r1 # r0 = A, r1 = B 8: 84 41 43 MOVW %r1,%r3 MULW3 %r0,%r1,%r3 # %r3 = A * B b: a8 40 43 MULW2 %r0,%r3 e: 37 1b BSBB GCD # Find the greatest common divisor GCD(A, B) 10: 9c 0c 4c ADDW2 &12,%sp DIVW3 %r0,%r3,%r0 # %r0 = A * B / GCD(A, B) = LCM 13: ec 40 43 e4 cc f4 DIVW3 %r0,%r3,{sword}-12(%sp) 19: 70 NOP 1a: 84 e4 cc f4 40 MOVW {sword}-12(%sp),%r0 1f: bc 0c 4c SUBW2 &12,%sp 22: 84 e4 40 40 MOVW {sword}%r0,%r0 26: 20 43 POPW %r3 # Restore the saved register and return 28: 08 RET # Return to the calling function GCD() GCD: #include "gcdivis.s" /* Return in %r0 the greatest common divisor of the numbers in %r0 and %r1 * (algorithm - Euclid of Alexandria, x86 implementation: Paul Hsieh). */ 29: fc 40 00 40 SUBW3 %r0,&0,%r0#NEGW #unsigned gcd(unsigned a, unsigned b) 2d: 7f 13 BEB L3 # { if (a == 0 && b == 0) return 1; 2f: fc 40 00 42 L1: SUBW3 %r0,&0,%r2#NEGW __ 33: 84 41 40 MOVW %r1,%r0#exchange/*\*/ 36: 84 42 41 MOVW %r2,%r1#r0 and r1 \ if (b == 0) return a; 39: bc 41 40 L2: SUBW2 %r1,%r0 # \ if (a != 0) 3c: 57 fd BGUB L2 # \__ while (a != b) 3e: 5b f1 BLUB L1 #___ / if (a < b) 40: 9c 41 40 L3: ADDW2 %r1,%r0 # X b -= a; 43: 74 RNEQ #__/ \_ else a -= b; 44: 90 40 INCW %r0 # return b; 46: 78 RSB # } 47: 70 NOP 68K GAS lcmult.s page 1 1 | Върни в D0 най-малкото общо кратно (НОК) на числата в SP(4) -> D0 и 2 | SP(8) -> D1 3 4 .global lcmult 5 lcmult: 6 0000 4CEF 0003 0004 MOVEML 4(%SP),%D0-%D1 | D0 = A, D1 = B 7 0006 48E7 3000 MOVEML %D2-%D3,-(%SP) | GCC изисква D2 и следващите да се съхраняват 8 000a 2601 MOVEL %D1,%D3 9 000c 4C00 3402 MULUL %D0,%D2:%D3 | D2:D3 = A * B 10 0010 610C BSRB GCD | намери НОД(A, B) 11 0012 4C40 3402 DIVUL %D0,%D2:%D3 12 0016 2003 MOVEL %D3,%D0 | D0 = A * B / НОД(A, B) = НОК 13 0018 4CDF 000C MOVEML (%SP)+,%D2-%D3 14 001c 4E75 RTS | Върни се в извикващата програма 15 GCD: 16 .include "gcdivis.s" 1 | Върни в D0 най-големия общ делител на числата в D0 и D1 2 | (алгоритъм - Евклид от Александрия, реализация за x86: Paul Hsieh). 3 4 001e 4480 NEGL %D0 | unsigned gcd(unsigned a, unsigned b) 5 0020 670A BEQB L3 | { 6 0022 4480 L1: NEGL %D0 | if (a == 0 && b == 0) return 1; 7 0024 C141 EXG %D0,%D1 |\ if (b == 0) return a; 8 0026 9081 L2: SUBL %D1,%D0 | \ if (a != 0) 9 0028 62FC BHIB L2 | \_ while (a != b) 10 002a 65F6 BLOB L1 | if (a < b) 11 002c D081 L3: ADDL %D1,%D0 |\ b -= a; 12 002e 6602 BNEB L4 | \_ else a -= b; 13 0030 5280 ADDQL #1,%D0 | return b; 14 0032 4E75 L4: RTS | } x86 NASM lcmult.s 1 ; Върни в EAX най-малкото общо кратно (НОК) на числата в EAX и EDX 2 3 section .text 4 global lcmult,_lcmult ; в GCC декларирай с __attribute__((regparm(3))) 5 lcmult: 6 _lcmult: 7 00000000 53 PUSH EBX ; GCC изисква да се съхрани EBX 8 00000001 89C1 MOV ECX,EAX ; съхрани числото A 9 00000003 89D3 MOV EBX,EDX ; съхрани числото B 10 00000005 F7E2 MUL EDX ; EDX:EAX = A * B 11 00000007 91 XCHG EAX,ECX ; EAX = A, ECX = младша_дума(A * B) 12 00000008 87D3 XCHG EDX,EBX ; EDX = B, EBX = старша_дума(A * B) 13 0000000A E807000000 CALL GCD ; намери НОД(A, B) 14 0000000F 91 XCHG EAX,ECX ; EAX = младша_дума(A * B), ECX = НОД 15 00000010 89DA MOV EDX,EBX ; EDX = старша_дума(A * B) 16 00000012 F7F1 DIV ECX ; EAX = A * B / НОД(A, B) = НОК 17 00000014 5B POP EBX ; (при деленето е възможно препълване, нищо че НОД > 0) 18 00000015 C3 RET 19 GCD: 20 %include "gcdivis.s" 1 <1> ; Върни в EAX най-големия общ делител на числата в EAX и EDX 2 <1> ; (алгоритъм - Евклид от Александрия, реализация: Paul Hsieh). 3 <1> 4 00000016 F7D8 <1> NEG EAX ; unsigned gcd(unsigned a, unsigned b) 5 00000018 7409 <1> JE L3 ; { 6 0000001A F7D8 <1> L1: NEG EAX ; if (a == 0 && b == 0) return 1; 7 0000001C 92 <1> XCHG EAX,EDX ;\ if (b == 0) return a; 8 0000001D 29D0 <1> L2: SUB EAX,EDX ; \ if (a != 0) 9 0000001F 77FC <1> JA L2 ; \_ while (a != b) 10 00000021 72F7 <1> JB L1 ; if (a < b) 11 00000023 01D0 <1> L3: ADD EAX,EDX ;\ b -= a; 12 00000025 7501 <1> JNE L4 ; \_ else a -= b; 13 00000027 40 <1> INC EAX ; return b; 14 00000028 C3 <1> L4: RET ; } ARM GAS lcmult.s page 1 1 // Върни в R0 най-малкото общо кратно (НОК) на числата в R0 и R1 2 // (произведението им трябва да е до 32 бита поради ограничението на 3 // командата UDIV; ARMv7 няма команда за делене с 64-битово делимо). 4 5 .global lcmult 6 lcmult: 7 0000 04E02DE5 STR LR,[SP,#-4]!//Съхрани LR, защото BL ще го промени! 8 0004 910002E0 MUL R2,R1,R0// R2 = A * B (няма смисъл от UMULL, защото няма UDIVL) 9 0008 010000EB BL GCD // намери НОД(A, B) 10 000c 12F030E7 UDIV R0,R2,R0// R0 = A * B / НОД(A, B) = НОК 11 0010 04F09DE4 LDR PC,[SP],#4//Върни се в извикващата програма 12 GCD: 13 .include "gcdivis.s" 1 // Върни в R0 най-големия общ делител на числата в R0 и R1 2 // (алгоритъм - Евклид от Александрия). 3 4 0014 013090E1 ORRS R3,R0,R1 //unsigned gcd(unsigned a, unsigned b) 5 0018 0100A003 MOVEQ R0,#1 //{ 6 001c 00005113 CMPNE R1,#0 //\__ if (a == 0 && b == 0) return 1; 7 0020 1EFF2F01 BXEQ LR // if (b == 0) return a; 8 0024 000050E3 CMP R0,#0 // if (a != 0) 9 0028 0100A001 MOVEQ R0,R1 // ___ while (a != b) 10 002c 010050E1 L1: CMP R0,R1 //___/ if (a < b) 11 0030 00104130 SUBLO R1,R1,R0 // b -= a; 12 0034 01004080 SUBHI R0,R0,R1 // else a -= b; 13 0038 FBFFFF1A BNE L1 // return b; 14 003c 1EFF2FE1 BX LR //} ARC GAS lcmult.s page 1 1 # Върни в r0 най-малкото общо кратно (НОК) на числата в r0 и r1 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата DIVU; ARCv2 няма команда за делене с 64-битово делимо. 4 5 .global lcmult 6 lcmult: 7 0000 E343 MOV_S r3,blink # Съхрани blink, защото BL_S ще го промени! 8 0002 1A21 0200 MPY r2,r1,r0 # r2 = A * B (няма смисъл от MPYDU, защото няма DIVDU) 9 0006 03F8 BL_S GCD # намери НОД(A, B) 10 0008 052A 0000 DIVU r0,r2,r0 # r0 = A * B / НОД(A, B) = НОК 11 000c 2020 C000 J [r3] # Върни се в извикващата програма 12 GCD: 13 .include "gcdivis.s" 1 # Върни в r0 най-големия общ делител на числата в r0 и r1 2 # (алгоритъм - Евклид от Александрия). 3 4 0010 0520 7E80 OR.F 0,r0,r1 #unsigned gcd(unsigned a, unsigned b) 5 0014 CA20 6100 MOV.Z r0,1 #{ if (a == 0 && b == 0) return 1; 6 0018 0AE9 BREQ_S r1,0,L2 # if (b == 0) return a; 7 001a 1470 CMP_S r0,0 # if (a != 0) 8 001c CA20 4100 MOV.EQ r0,r1 # ___ while (a != b) 9 0020 3070 L1: CMP_S r0,r1 #___/ if (a < b) 10 0022 C221 0500 SUB.LO r1,r1,r0 # b -= a; 11 0026 C220 4D00 SUB.HI r0,r0,r1 # else a -= b; 12 002a FCF5 BNE_S L1 # return b; 13 002c E07E L2: J_S [blink] #} PPC GAS lcmult.s page 1 1 # Върни в r3 най-малкото общо кратно (НОК) на числата в r3 и r4 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата divwu; PowerPC няма команда за делене с 64-битово делимо). 4 5 .global lcmult 6 lcmult: 7 0000 7CE802A6 mflr r7 # Съхрани lr, защото bl ще го промени! 8 0004 7CA419D6 mullw r5,r4,r3# r5 = A * B 9 0008 48000011 bl GCD # намери НОД(A, B) 10 000c 7C651B96 divwu r3,r5,r3# r3 = A * B / НОД(A, B) = НОК 11 0010 7CE803A6 mtlr r7 12 0014 4E800020 blr # Върни се в извикващата програма 13 GCD: 14 .include "gcdivis.s" 1 # Върни в r3 най-големия общ делител на числата в r3 и r4 2 # (алгоритъм - Евклид от Александрия). 3 4 0018 7C662379 or. r6,r3,r4 #unsigned gcd(unsigned a, unsigned b) 5 001c 40820008 bne L1 #{ 6 0020 38600001 li r3,1 #____ if (a == 0 && b == 0) 7 0024 28040000 L1: cmplwi r4,0 # \__ return 1; 8 0028 4D820020 beqlr #___ if (b == 0) 9 002c 28030000 cmplwi r3,0 #__ \___ return a; 10 0030 40820008 bne L2 # \ 11 0034 7C832378 mr r3,r4 # \__ if (a != 0) 12 0038 7C032040 L2: cmplw r3,r4 # while (a != b) 13 003c 4080000C bge L3 # if (a < b) 14 0040 7C832050 subf r4,r3,r4 # b -= a; 15 0044 4BFFFFF4 b L2 # else 16 0048 4D820020 L3: beqlr # a -= b; 17 004c 7C641850 subf r3,r4,r3 # return b; 18 0050 4BFFFFE8 b L2 #} SPARC GAS lcmult.S page 1 1 ! Върни в %o0 най-малкото общо кратно (НОК) на числата в %o0 и %o1 2 3 .global lcmult 4 lcmult: 5 0000 9810000F mov %o7,%o4 ! Съхрани %o7, защото „call“ ще го промени! 6 0004 40000004 call GCD ! намери НОД(A, B) 7 0008 96520009 umul %o0,%o1,%o3 ! %y:%o3 = A * B (изпълнява се преди „call“!) 8 000c 81C32008 jmpl %o4+8,%g0 ! Върни се в извикващата програма 9 0010 9072C008 udiv %o3,%o0,%o0 ! %o0 = A * B / НОД(A, B) = НОК (преди „jmpl“!) 10 GCD: 11 #include "gcdivis.s" SPARC GAS gcdivis.s page 1 1 ! Върни в %o0 най-големия общ делител на числата в %o0 и %o1 2 ! (алгоритъм - Евклид от Александрия, реализация за x86: Paul Hsieh). 3 4 0000 90A00008 subcc %g0,%o0,%o0!negcc!unsigned gcd(unsigned a, unsigned b) 5 0004 02800009 be L3 ! { if (a == 0 && b == 0) return 1; 6 0008 94200008 L1: sub %g0,%o0,%o2!neg ___ 7 000c 90100009 mov %o1,%o0 !размени /*\*/ 8 0010 9210000A mov %o2,%o1 !%o0,%o1 \ if (b == 0) return a; 9 0014 90A20009 L2: subcc %o0,%o1,%o0 ! \ if (a != 0) 10 0018 18BFFFFF bgu L2 ! \_ while (a != b) 11 001c 01000000 nop ! / 12 0020 0ABFFFFA bcs L1 !_ / if (a < b) 13 0024 01000000 nop ! \ / 14 0028 90820009 L3: addcc %o0,%o1,%o0 ! X b -= a; 15 002c 12800003 bne L4 !_/ \_ else a -= b; 16 0030 01000000 nop 17 0034 90022001 inc %o0 ! return b; 18 0038 81C3E008 L4: retl ! } 19 003c 01000000 nop MIPS GAS lcmult.s page 1 1 # Върни в $2 най-малкото общо кратно (НОК) на числата в $4 и $5 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата DIVU; MIPS32 няма команда за делене с 64-битово делимо). 4 5 .ent lcmult 6 .global lcmult 7 lcmult: 8 0000 03E03021 MOVE $6,$31 # Съхрани $31, защото BAL ще го промени! 9 MUL $7,$4,$5# $7 = A * B 10 0004 04110007 70853802 BAL GCD # намери НОД(A, B) 11 000c 14800002 00E4001B 0007000D DIVU $7,$4 # LO = A * B / НОД(A, B) = НОК 11 00003812 12 MFLO $2 13 001c 00C00008 00001012 JR $6 # Върни се в извикващата програма 14 GCD: 15 .include "gcdivis.s" 1 # Върни в $4 най-големия общ делител на числата в $4 и $5 2 # (алгоритъм - Евклид от Александрия). 3 4 0024 00851025 OR $2,$4,$5 #unsigned gcd(unsigned a, unsigned b) 5 0028 14400002 00000000 BNE $2,$0,L1 #{ 6 0030 24040001 LI $4,1 # if (a == 0 && b == 0) return 1; 7 0034 14A00003 00000000 L1: BNE $5,$0,L3 # if (b == 0) 8 003c 03E00008 00000000 L2: JR $31 # return a; 9 0044 00A4200A L3: MOVZ $4,$5,$4 # if (a != 0) 10 0048 0085082B 10200003 00000000 L4: BGEU $4,$5,L5 # while (a != b) 11 SUBU $5,$5,$4 # if (a < b) 12 0054 1000FFFC 00A42823 B L4 # b -= a; 13 005c 1085FFF7 00000000 L5: BEQ $4,$5,L2 # else 14 SUBU $4,$4,$5 # a -= b; 15 0064 1000FFF8 00852023 B L4 # return b; } 16 006c 00000000 .end lcmult RISC-V GAS lcmult.s page 1 1 # Върни в a0 най-малкото общо кратно (НОК) на числата в a0 и a1 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата DIVU; RV32 няма команда за делене с 64-битово делимо). 4 5 .global lcmult 6 lcmult: 7 0000 0686 MV a2,ra # Съхрани ra, защото JAL ще го промени! 8 0002 B306B502 MUL a3,a0,a1 # a3 = A * B 9 0006 EF00A000 JAL ra,GCD # намери НОД(A, B) 10 000a 33D5A602 DIVU a0,a3,a0 # aO = A * B / НОД(A, B) = НОК 11 000e 0286 JR a2 # Върни се в извикващата програма 12 GCD: 13 .include "gcdivis.s" 1 # Върни в a0 най-големия общ делител на числата в a0 и a1 2 # (алгоритъм - Евклид от Александрия). 3 4 0010 3367B500 OR a4,a0,a1 #unsigned gcd(unsigned a, unsigned b) 5 0014 11E3 BNE a4,x0,L1 #{ 6 0016 0545 LI a0,1 # if (a == 0 && b == 0) return 1; 7 0018 91E1 L1: BNEZ a1,L3 # if (b == 0) 8 001a 8280 L2: RET # return a; 9 001c 11E1 L3: BNEZ a0,L4 # if (a != 0) 10 001e 2E85 MV a0,a1 11 0020 6374B500 L4: BGEU a0,a1,L5 # while (a != b) 12 0024 898D SUB a1,a1,a0 # if (a < b) 13 0026 EDBF J L4 # b -= a; 14 0028 E309B5FE L5: BEQ a0,a1,L2 # else 15 002c 0D8D SUB a0,a0,a1 # a -= b; 16 002e CDBF J L4 # return b; } Nios II GAS lcmult.s page 1 1 # Върни в r2 най-малкото общо кратно (НОК) на числата в r4 и r5 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата DIVU; Nios II няма команда за делене с 64-битово делимо). 4 5 .global lcmult 6 lcmult: 7 0000 3A880DF8 MOV r6,ra # Съхрани ra, защото CALL ще го промени! 8 0004 3A384F21 MUL r7,r4,r5 # r7 = A * B 9 0008 00000000 CALL GCD # намери НОД(A, B) 10 000c 3A200539 DIVU r2,r7,r4 # r4 = A * B / НОД(A, B) = НОК 11 0010 3A680030 JMP r6 # Върни се в извикващата програма 12 GCD: 13 .include "gcdivis.s" 1 # Върни в r4 най-големия общ делител на числата в r4 и r5 2 # (алгоритъм - Евклид от Александрия). 3 4 0014 3AB04421 OR r2,r4,r5 #unsigned gcd(unsigned a, unsigned b) 5 0018 1E010010 BNE r2,r0,L1 #{ 6 001c 54000001 MOVUI r4,1 # if (a == 0 && b == 0) return 1; 7 0020 1E010028 L1: BNE r5,r0,L3 # if (b == 0) 8 0024 3A2800F8 L2: RET # return a; 9 0028 1E010020 L3: BNE r4,r0,L4 # if (a != 0) 10 002c 3A880928 MOV r4,r5 11 0030 2E024021 L4: BGEU r4,r5,L5 # while (a != b) 12 0034 3AC80B29 SUB r5,r5,r4 # if (a < b) 13 0038 06FD3F00 BR L4 # b -= a; 14 003c 26F97F21 L5: BEQ r4,r5,L2 # else 15 0040 3AC84921 SUB r4,r4,r5 # a -= b; 16 0044 06FA3F00 BR L4 # return b; } Xtensa GAS lcmult.s page 1 1 # Върни в a2 най-малкото общо кратно (НОК) на числата в a2 и a3 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата DIVU; Xtensa няма команда за делене с 64-битово делимо). 4 5 .global lcmult 6 lcmult: 7 0000 4D00 MOV a4,a0 # Съхрани a0, защото CALL0 ще го промени! 8 0002 305282 MULL a5,a2,a3 # a5 = A * B 9 0005 850000 CALL0 GCD # намери НОД(A, B) 10 0008 2025C2 QUOU a2,a5,a2 # aO = A * B / НОД(A, B) = НОК 11 000b A00400 JX a4 # Върни се в извикващата програма 12 000e 0000 .align 4 13 GCD: 14 .include "gcdivis.s" 1 # Върни в a2 най-големия общ делител на числата в a2 и a3 2 # (алгоритъм - Евклид от Александрия). 3 4 0010 306220 OR a6,a2,a3 #unsigned gcd(unsigned a, unsigned b) 5 0013 561600 BNEZ a6,L1 #{ 6 0016 0C12 MOVI a2,1 # if (a == 0 && b == 0) return 1; 7 0018 CC03 L1: BNEZ a3,L3 # if (b == 0) 8 001a 0DF0 L2: RET # return a; 9 001c CC02 L3: BNEZ a2,L4 # if (a != 0) 10 001e 2D03 MOV a2,a3 11 0020 37B205 L4: BGEU a2,a3,L5 # while (a != b) 12 0023 2033C0 SUB a3,a3,a2 # if (a < b) 13 0026 86FDFF J L4 # b -= a; 14 0029 3712ED L5: BEQ a2,a3,L2 # else 15 002c 3022C0 SUB a2,a2,a3 # a -= b; 16 002f 46FBFF J L4 # return b; } 88K GAS lcmult.s page 1 1 # Върни в r2 най-малкото общо кратно (НОК) на числата в r2 и r3 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата divwu; M88K няма команда за делене с 64-битово делимо). 4 5 .global _lcmult 6 0000 F4C15800 _lcmult: 7 0004 F4836C02 or r6,r1,r0 # Съхрани lr, защото bl ще го промени! 8 0008 C8000003 mul r4,r3,r2 # r4 = A * B 9 000c F4446802 bsr GCD # намери НОД(A, B) 10 0010 F400C006 divu r2,r4,r2 # r2 = A * B / НОД(A, B) = НОК 11 jmp r6 # Върни се в извикващата програма 12 GCD: 13 .include "gcdivis.s" 1 # Върни в r2 най-големия общ делител на числата в r2 и r3 2 # (алгоритъм - Евклид от Александрия). 3 4 0014 F4A25803 or r5,r2,r3 #unsigned gcd(unsigned a, unsigned b) 5 0018 E9A50002 bcnd ne0,r5,L1 #{ 6 001c 58400001 or r2,r0,1 # if (a == 0 && b == 0) return 1; 7 0020 E8430008 L1: bcnd eq0,r3,L4 # if (b == 0) return a; 8 0024 E9A20002 bcnd ne0,r2,L2 # if (a != 0) 9 0028 F4435800 or r2,r3,r0 # 10 002c F4A27C03 L2: cmp r5,r2,r3 # while (a != b) 11 0030 D9650003 bb1 hs,r5,L3 # if (a < b) 12 0034 F4636402 subu r3,r3,r2 # b -= a; 13 0038 C3FFFFFD br L2 # else 14 003c D8650002 L3: bb1 ne,r5,L5 # ______ a -= b; 15 0040 F400C001 L4: jmp r1 # return b; / 16 0044 F4426403 L5: subu r2,r2,r3 # _____________________/ 17 0048 C3FFFFF9 br L2 #} Or1k GAS lcmult.s page 1 1 # Върни в R11 най-малкото общо кратно (НОК) на числата в R3 и R4 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата L.DIVU; OpenRISC няма команда за делене с 64-битово делимо). 4 5 .global lcmult 6 lcmult: 7 0000 E0A90004 L.OR R5,LR,R0 # Съхрани LR, защото L.JAL ще го промени! 8 0004 04000004 L.JAL GCD # намери НОД(A, B) 9 0008 E0C3230B L.MULU R6,R3,R4 # R6 = A * B (изпълнява се преди „L.JAL“!) 10 000c 44002800 L.JR R5 # Върни се в извикващата програма 11 0010 E1661B0A L.DIVU R11,R6,R3# R11 = A * B / НОД(A, B) = НОК (изп.се преди „L.JR“!) 12 GCD: 13 .include "gcdivis.s" 1 # Върни в R11 най-големия общ делител на числата в R3 и R4 2 # (алгоритъм - Евклид от Александрия, реализация за x86: Paul Hsieh). 3 4 0014 E0601802 L.SUB R3,R0,R3#NEG # unsigned gcd(unsigned a, unsigned b) 5 0018 E4030000 L.SFEQ R3,R0 # { 6 001c 1000000B L.BF L3 # if (a == 0 && b == 0) return 1; 7 0020 15000000 L.NOP 0 8 0024 E0E01802 L1: L.SUB R7,R0,R3#NEG ___ 9 0028 E0640004 L.OR R3,R4,R0#размени /*\*/ 10 002c E0870004 L.OR R4,R7,R0#R3,R4 \ if (b == 0) return a; 11 0030 E4432000 L2: L.SFGTU R3,R4 # \ if (a != 0) 12 0034 13FFFFFF L.BF L2#изп.се след L.SUB/*\*/ 13 0038 E0632002 L.SUB R3,R3,R4 # \_ while (a != b) 14 003c E4030000 L.SFEQ R3,R0 # / 15 0040 0FFFFFF9 L.BNF L1 #__ / if (a < b) 16 0044 15000000 L.NOP 0 # \ / 17 0048 E0632000 L3: L.ADD R3,R3,R4 # X b -= a; 18 004c E4030000 L.SFEQ R3,R0 # / \_ else a -= b; 19 0050 0C000003 L.BNF L4 #_/ 20 0054 15000000 L.NOP 0 21 0058 9C630001 L.ADDI R3,R3,1 # return b; 22 005c 44004800 L4: L.JR LR # } 23 0060 15000000 L.NOP 0 Xilinx MicroBlaze GAS lcmult.s page 1 1 # Върни в R3 най-малкото общо кратно (НОК) на числата в R5 и R6 2 # (произведението им трябва да е до 32 бита поради ограничението на 3 # командата divwu; MicroBlaze няма команда за делене с 64-битово делимо). 4 5 .global lcmult 6 lcmult: 7 0000 00002F81 OR R9,R15,R0# Съхрани R15, защото „BRLID“ ще го промени! 8 0004 1000F4B9 BRLID R15,GCD # намери НОД(A, B) 9 0008 0028E640 MUL R7,R6,R5 # r5 = A * B (изпълнява се преди „BRLID“!) 10 000c 080009B6 RTSD R9,8 # Върни се в извикващата програма 11 0010 02386548 IDIVU R3,R5,R7 # r3 = A * B / НОД(A, B) = НОК (изп. се преди „RTSD“!) 12 GCD: 13 .include "gcdivis.s" 1 # Върни в R5 най-големия общ делител на числата в R5 и R6 2 # (алгоритъм - Евклид от Александрия). 3 4 0014 00300581 OR R8,R5,R6 #unsigned gcd(unsigned a, unsigned b) 5 0018 080028BC BNEI R8,L1 #{ 6 001c 0100A0A0 ORI R5,R0,1 # if (a == 0 && b == 0) 7 0020 280006BC L1: BEQI R6,L4 # return 1; 8 0024 080025BC BNEI R5,L2 #___ if (b == 0) return a; 9 0028 0000A680 OR R5,R6,R0 # \__ if (a != 0) 10 002c 03280615 L2: CMPU R8,R6,R5 # while (a != b) 11 0030 0C00A8BC BGEI R8,L3 # if (a < b) 12 0034 0030C504 RSUB R6,R5,R6 # b -= a; 13 0038 F4FF00B8 BRI L2 # else 14 003c 0C0008BC L3: BEQI R8,L4 # a -= b; 15 0040 0028A604 RSUB R5,R6,R5 # return b; 16 0044 E8FF00B8 BRI L2 #} 17 0048 08000FB6 L4: RTSD R15,8 18 004c 00000080 NOP 19 20 # При R6 = 0 и R5 = 0x80000000 командата „L2: CMPU R8,R6,R5“ ще върне R8 = 0! 21 # За радост, програмата изобщо не стига до тази точка при такива стойности... HPPA GAS lcmult.s page 1 1 ; Върни в %R28 най-малкото общо кратно (НОК) на числата в регистри %R26 и %R25 2 ; (произведението им трябва да е до 32 бита заради опростения метод на делене). 3 ; Деленето е версия с цикъл на $$divU от „hp-milli.s“, © Hewlett-Packard, 1986. 4 5 .text 6 .global lcmult,UDIV 7 lcmult: 8 0000 0FD91281 STW %R25,-16(%SP) 9 0004 0FDA1289 STW %R26,-12(%SP) ; Съхрани аргументите в стека 10 0008 2FC11016 FLDDS -16(%SP),%FR22 ; Зареди ги в двете половини на FR22 11 000c 3AD65716 XMPYU %FR22L,%FR22R,%FR22; FR22 = A * B 12 0010 2FC11216 FSTDS %FR22,-16(%SP) ; Съхрани цялото произведение обратно в стека 13 0014 E8200060 BL GCD,%R1 ; R26 = НОД(A, B); изпълнява се след „LDW“! 14 0018 0FC91098 LDW -12(%SP),%R24 ; R24 = A * B (само младшата дума) 15 001c 3401003E UDIV: LDI 31,%R1 ; Брояч на цикъла (R24: делимо, R26: делител) 16 0020 0B40041D SUB %R0,%R26,%R29 ; Вдигни най-старшия бит на R29 и нулирай C 17 0024 0BA00440 DS %R0,%R29,%R0 ; Установи бит V (корекция на „DS“) в лог. 1 18 0028 0B180618 ADD %R24,%R24,%R24 ; Най-левият C = най-старшия бит на делимото 19 002c 0B40045D DS %R0,%R26,%R29 ; Първа стъпка на деленето, ако няма пренос 20 0030 0B180718 L0: ADDC %R24,%R24,%R24 ; Ротация на делимо / частно през C наляво 21 0034 AC3F3FED ADDIBF,= -1,%R1,L0 ; Следваща итерация (изпълнява се след „DS“!) 22 0038 0B5D045D DS %R29,%R26,%R29 ; Поредна стъпка на деленето... 23 003c 0B18071C ADDC %R24,%R24,%R28 ; Вмъкни и последния бит в частното 24 0040 93A06000 COMICLR,<= 0,%R29,%R0 ; При положителен остатък прескочи корекцията 25 0044 0B5D061D ADD %R29,%R26,%R29 ; Коригирай отриц. остатък / R28: частно 26 0048 E840C002 BV,N (%R2) ; R28 = A * B / НОД(A, B) = НОК; R29: остатък 27 GCD: 28 .include "gcdivis.s" 1 ; Върни в %R26 най-големия общ делител на числата в %R26 и %R25 2 ; (алгоритъм - Евклид от Александрия). 3 4 004c 0B593240 OR,<> %R25,%R26,%R0 ;unsigned gcd(unsigned a, unsigned b) 5 0050 341A0002 LDI 1,%R26 ;{ 6 0054 0B393240 OR,<> %R25,%R25,%R0 ; if (a == 0 && b == 0) return 1; 7 0058 E820C002 L1: BV,N (%R1) ; if (b == 0) 8 005c 0B5A3240 OR,<> %R26,%R26,%R0 ; return a; 9 0060 0819025A COPY %R25,%R26 ; if (a != 0) 10 0064 0B593400 L2: SUB,<> %R25,%R26,%R0 ; while (a != b) 11 0068 E81F1FD7 B,N L1 12 006c 0B59A400 SUB,<<= %R25,%R26,%R0 ; if (a < b) 13 0070 0B590419 SUB %R25,%R26,%R25 ; b -= a; 14 0074 0B3AA400 SUB,<<= %R26,%R25,%R0 ; else 15 0078 0B3A041A SUB %R26,%R25,%R26 ; a -= b; 16 007c E81F1FC7 B,N L2 ; return b; } Renesas / SuperH SH GAS Little Endian lcmult.s page 1 1 ! Върни в R0 най-малкото общо кратно (НОК) на числата в R4 и R5 2 ! Деленето е вариант с цикъл на пример №2, горе на стр. 242 в REJ09B0318-0600 3 4 .global lcmult,UDIV 5 lcmult: 6 0000 2A07 STS PR,R7 ! Съхрани адреса на връщане, защото BSR ще го промени 7 0002 0FB0 BSR GCD ! R4 = НОД(A, B) 8 0004 4535 DMULU.L R4,R5 ! MACH:MACL = A * B (изпълнява се преди „BSR“!) 9 0006 2A47 LDS R7,PR ! Възстанови адреса на връщане 10 0008 0A01 UDIV: STS MACH,R1 ! R4 = делител, MACH:MACL = делимо 11 000a 1A00 STS MACL,R0 ! R1:R0 = делимо 12 000c 20E3 MOV #32,R3 ! Изваждащ брояч на итерациите 13 000e 00E2 MOV #0,R2 ! Заради бит 0 14 0010 1900 DIV0U ! Инициализай флаговете за делене на числа без знак 15 0012 0142 L0: SHLR R2 ! Възстанови T 16 0014 2440 ROTCL R0 17 0016 4431 DIV1 R4,R1 ! Поредна стъпка делене 18 0018 2902 MOVT R2 ! ROTCL и DIV1 работят с T – съхрани състоянието му 19 001a 1043 DT R3 ! Последна итерация? 20 001c F98B BF L0 ! Не, продължи 21 001e 0142 SHLR R2 ! Да, пак възстанови T 22 0020 0B00 RTS ! Върни управлението (изпълнява се след „ROTCL“!) 23 0022 2440 ROTCL R0 ! с частното в R0 = A * B / НОД(A, B) = НОК 24 GCD: 25 .include "gcdivis.s" 1 ! Върни в R4 най-големия общ делител на числата в R4 и R5 2 ! (алгоритъм - Евклид от Александрия). 3 4 0024 00E0 MOV #0,R0 5 0026 4366 MOV R4,R6 !unsigned gcd(unsigned a, unsigned b) 6 0028 5B26 OR R5,R6 !{ 7 002a 0036 CMP/EQ R0,R6 ! if (a == 0 && b == 0) 8 002c 008B BF L1 9 002e 01E4 MOV #1,R4 ! return 1; 10 0030 0035 L1: CMP/EQ R0,R5 ! if (b == 0) 11 0032 0A89 BT L4 ! return a; 12 0034 0034 CMP/EQ R0,R4 ! if (a != 0) 13 0036 008B BF L2 14 0038 5364 MOV R5,R4 15 003a 4635 L2: CMP/HI R4,R5 ! while (a != b) 16 003c 018B BF L3 ! if (a < b) 17 003e FCAF BRA L2!изп.се след SUB! 18 0040 4835 SUB R4,R5 ! b -= a; 19 0042 5034 L3: CMP/EQ R5,R4 20 0044 0189 BT L4 21 0046 F8AF BRA L2!изп.се след SUB! else 22 0048 5834 SUB R5,R4 ! a -= b; 23 004a 0B00 L4: RTS ! return b; 24 004c 0900 NOP !} GAS for CRIS lcmult.s page 1 1 ; Върни в R10 най-малкото общо кратно (НОК) на числата в R10 и R11 2 ; 3 ; Произведението им трябва да е до 16 бита, поради ограничението на командата 4 ; DSTEP. CRIS няма команда за делене – за командата DIV на стр. 15 в „Porting 5 ; The Gnu C Compiler to the CRIS architecture“ Hans-Peter Nilsson пише: „This 6 ; instruction was removed before CRIS went into silicon. It was replaced with 7 ; an instruction called dstep, which implements a part of the division shift 8 ; and conditionally subtract.“ 9 10 .global lcmult,UDIV16 11 lcmult: 12 0000 7FB6 MOVE $SRP,$R15 ; Съхрани SRP, защото „BSR“ ще го промени! 13 0002 6BD6 MOVE.D $R11,$R13 14 0004 BFBE3E00 0000 BSR GCD ; Намери НОД(A, B) 15 000a 2AD9 MULU.D $R10,$R13 ; MOF:R13 = A * B (изпълнява се преди „BSR“!) 16 000c 6AB6 MOVE.D $R10,$R11 ; НОД 17 000e 6DA6 MOVE.D $R13,$R10 ; A * B 18 0010 3F76 MOVE $R15,$MOF ; „UDIV16“ ще се извиква с „BAS UDIV16,$MOF“ 19 0012 D0B3 UDIV16: LSLQ 16,$R11 ; Вход: R11 = делимо, R10 = делител (16-битови) 20 0014 81B2 SUBQ 1,$R11 ; Вж. „ETRAX FS Designer’s Reference“, стр. 76 21 0016 FBA6 DSTEP $R11,$R10 ; Поредицата от DSTEP не може да бъде циклична! 22 0018 FBA6 DSTEP $R11,$R10 23 001a FBA6 DSTEP $R11,$R10 24 001c FBA6 DSTEP $R11,$R10 25 001e FBA6 DSTEP $R11,$R10 26 0020 FBA6 DSTEP $R11,$R10 27 0022 FBA6 DSTEP $R11,$R10 28 0024 FBA6 DSTEP $R11,$R10 29 0026 FBA6 DSTEP $R11,$R10 30 0028 FBA6 DSTEP $R11,$R10 31 002a FBA6 DSTEP $R11,$R10 32 002c FBA6 DSTEP $R11,$R10 33 002e FBA6 DSTEP $R11,$R10 34 0030 FBA6 DSTEP $R11,$R10 35 0032 FBA6 DSTEP $R11,$R10 36 0034 FBA6 DSTEP $R11,$R10 37 0036 6AB6 MOVE.D $R10,$R11 ; R10 старши 16 бита = остатък, младши = частно 38 0038 F0B3 LSRQ 16,$R11 ; R11 = остатък 39 003a F079 JUMP $MOF ; Върни се в извикващата програма 40 003c 2FAFFFFF 0000 AND.D 0xFFFF,$R10 ; R10 = A * B / НОД(A, B) = НОК (преди „JUMP“!) 41 GCD: 42 .include "gcdivis.s" 1 ; Върни в R10 най-големия общ делител на числата в R10 и R11 2 ; (алгоритъм - Евклид от Александрия, реализация за x86: Paul Hsieh). 3 4 0042 AAA5 NEG.D $R10,$R10 ; unsigned gcd(unsigned a, unsigned b) { 5 0044 1230 BEQ L3 ; if (a == 0 && b == 0) return 1; 6 0046 AAC5 L1: NEG.D $R10,$R12 ;__ 7 0048 6BA6 MOVE.D $R11,$R10;размени/*\*/ 8 004a 6CB6 MOVE.D $R12,$R11;R10,R11 \ if (b == 0) return a; 9 004c ABA6 L2: SUB.D $R11,$R10 ; \ if (a != 0) 10 004e FF90 BHI L2 ; \_ while (a != b) 11 0050 B005 NOP ; / 12 0052 F510 BLO L1 ;_ / if (a < b) 13 0054 B005 NOP ; \ / 14 0056 2BA6 L3: ADD.D $R11,$R10 ; X b -= a; 15 0058 0620 BNE L4 ;_/ \_ else a -= b; 16 005a B005 NOP 17 005c 01A2 ADDQ 1,$R10 ; return b; 18 005e F0B9 L4: RET ; } 19 0060 B005 NOP BFIN GAS lcmult.s page 1 1 # Върни в R0 най-малкото общо кратно (НОК) на числата в R0 и R1 2 # 3 # Произведението им трябва да е до 31 бита поради ограничение на командата DIVQ 4 # (Blackfin няма команда за делене). Освен това при твърде малък НОД може да се 5 # получи грешен резултат поради препълване, защото делителят е 15-битов. 6 7 .global _lcmult,_UDIV16 8 _lcmult: 9 0000 1930 R3 = R1; # B 10 0002 C340 R3 *= R0; # A * B 11 0004 0F33 P1 = RETS; # Съхрани RETS, защото „CALL“ ще го промени! 12 0006 00E30E00 CALL GCD; # Намери НОД(A, B) 13 000a 7938 RETS = P1; # Възстанови адреса на връщане 14 000c 0830 R1 = R0; # Делител (НОД) 15 000e 0330 R0 = R3; # Делимо (A * B) 16 0010 8268 _UDIV16:P2 = 16; # Вход: R0 = делимо < 2^31, R1 = делител < 2^15 17 0012 084F R0 <<= 1; # Делимото трябва да се удвои преди деленето 18 0014 8008 CC = R0 < R0; # (вж. примера в 82-000556-01, стр. 15-24/25) 19 0016 8603 AQ = CC; # Флагът на частното AQ = 0 (беззнаково делене) 20 0018 A2E00220 LSETUP (L_0, L_0) LC0 = P2;#Задай начало/край на цикъла и брой итерации 21 001c 0842 L_0: DIVQ (R0, R1); # Извърши деленето (тяло на цикъла – 1 команда) 22 001e C042 R0 = R0.L (Z); # R0 = частно (16 бита, без знак) 23 0020 1000 RTS; # Върни се в извикващата програма 24 GCD: 25 .include "gcdivis.s" 1 # Върни в R0 най-големия общ делител на числата в R0 и R1 2 # (алгоритъм - Евклид от Александрия). 3 4 0022 8856 R2 = R0 | R1; #unsigned gcd(unsigned a, unsigned b) 5 0024 0A02 CC = R2; #{ 6 0026 0218 IF CC JUMP L_1; # if (a == 0 && b == 0) 7 0028 0860 R0 = 1; # return 1; 8 002a 0902 L_1: CC = R1; 9 002c 0218 IF CC JUMP L_3; # if (b == 0) 10 002e 1000 L_2: RTS; # return a; 11 0030 0802 L_3: CC = R0; 12 0032 0218 IF CC JUMP L_4; # if (a != 0) 13 0034 0130 R0 = R1; 14 0036 010A L_4: CC = R1 <= R0 (IU); # while (a != b) 15 0038 0318 IF CC JUMP L_5; # if (a < b) 16 003a 4152 R1 = R1 - R0; # b -= a; 17 003c FD2F JUMP L_4; 18 003e 0808 L_5: CC = R0 == R1; 19 0040 F71B IF CC JUMP L_2; # else 20 0042 0852 R0 = R0 - R1; # a -= b; 21 0044 F92F JUMP L_4; # return b; } Hexagon GAS lcmult.S page 1 1 // Върни в регистър R0 най-малкото общо кратно (НОК) на числата в регистри R0 и 2 // R1 3 4 .global lcmult 5 lcmult: 6 { R8 = LR // Съхрани LR, защото „CALL“ ще го промени! 7 R7:6 = MPYU(R0,R1) // A * B 8 0000 064140E5 1040005A 08C07F70 CALL GCD } // Намери НОД(A, B) 9 { R2 = R0 // Делител 10 R0 = R6 // Младша дума на делимото 11 R1 = R7 // Старша " " " " 12 000c 00406670 01406770 02300328 R3 = #0 } // Адрес на остатъка NULL, за да не се запазва 13 0018 00C0005A CALL udiv64 // R0 = A * B / НОД(A, B) = НОК 14 001c 00C08852 JUMPR R8 // Върни се в извикващата програма 15 GCD: 16 #include "gcdivis.s" Hexagon GAS gcdivis.s page 1 1 // Върни в регистър R0 най-големия общ делител на числата в R0 и R1. 2 // Алгоритъм - Евклид от Александрия. 3 4 0000 02C120F1 R2 = OR(R0,R1) //unsigned gcd(unsigned a, unsigned b) 5 { P0 = CMP.GTU(R2,#0) //{ 6 IF (!P0.NEW) R0 = #1 // if (a == 0 && b == 0) 7 0004 00408275 00487F53 20E0807E IF (!P0.NEW) JUMPR:NT LR }// return 1; 8 0010 08C08161 IF (R1==#0) JUMP:NT L3 // if (b == 0) return a; 9 0014 04C08061 IF (R0==#0) JUMP:NT L2 // if (a != 0) 10 0018 00C100F2 L1: P0 = CMP.EQ(R0,R1) // while (a != b) 11 001c 00C00174 L2: IF (P0) R0 = R1 12 L3: { IF (P0) JUMPR LR 13 0020 004061F2 00C05F53 P0 = CMP.LTU(R0,R1) }// if (a < b) 14 { IF (P0) R1 = SUB(R1,R0)// b -= a; 15 IF (!P0) R0 = SUB(R0,R1)// else a -= b; 16 0028 014120FB F87FFF59 80C021FB JUMP L1 } // return b; } UNDEFINED SYMBOLS udiv64 S/390 GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър 2 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри 2, 3 и 4. 3 4 .global nsamebit 5 nsamebit: 6 0000 1732 XR 3,2 # 3 ^= 2 (съвпадащите битове стават 0, другите —— 1) 7 0002 1742 XR 4,2 # 4 ^= 2 ( " " " " " " " " " " ) 8 0004 1634 OR 3,4 9 0006 1333 LCR 3,3 10 0008 A73AFFFF AHI 3,-1 # 3 = ~(3 ^ 2 | 4 ^ 2) " " " 1, " " " 0) 11 000c A7480020 LHI 4,32 # Зареди брояча на битове 12 0010 1722 XR 2,2 # и брояча на лог. единици 13 0012 1755 XR 5,5 # Подготви събираемото за отчитането на преноса 14 0014 1E33 L1: ALR 3,3 # Изведи поредния бит в преноса 15 0016 B9980025 ALCR 2,5 # Преброй поредния бит като съвпадащ, ако е лог. 1 16 001a A746FFFD BRCT 4,L1 # Повтаряй до края на цикъла 17 001e 07FE BR 14 # Рег.2 = брой лог. единици в рег. 3 (съвпадащи битове) ==> id32/nsamebit.s <== 1 * Return in register 0 the number of the coincident bits on the same position 2 * in the words, passed in 7(0) -> reg. 0, 7(4) -> reg. 1, and 7(8) -> reg. 2. 3 4 entry nsamebit 00000000d 5 nsamebit equ * 00000d 5807 0000 6 l 0,0(7) The 3 arguments 00004d 5817 0004 7 l 1,4(7) 00008d 5827 0008 8 l 2,8(7) 0000Cd 0710 9 xr 1,0 1 ^= 0 (the coincident bits become 0, the rest - 1) 0000Ed 0720 10 xr 2,0 2 ^= 0 (" " " " " " " " " " " ) 00010d 0612 11 or 1,2 1 = 1 ^ 0 | 2 ^ 0 ( " " " " " " " " ) 00012d C710 FFFF 12 xi 1,-1(0) Make the coincident bits log. 1, non-coincident - 0 00016d 0700 13 xr 0,0 Initialise the counter of the logical ones 00018d 0821 14 L1 lr 2,1 0001Ad EC20 001F 15 srl 2,31 Save the highmost bit before shifting the rest 0001Ed 0A02 16 ar 0,2 Count the next bit as coincident, if it's a logical one 00020d 1111 17 slls 1,1 00022d 2035 00000018d 18 bnzs L1 Repeat while there are still logical ones in register 1 00024d 030F 19 br 15 Reg.0 = # of log. ones in reg.1 (i.e., coincident bits) VAX GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в AP(4,8,12) -> R0, R1 и R2. 3 4 .global _nsamebit 5 _nsamebit: 6 0000 0C00 .word 0xC # R2-R3 7 0002 FD7DAC04 50 MOVO 4(AP),R0# Аргументи 8 0007 CC5051 XORL2 R0,R1 # R1 ^= R0 (съвпадащите битове стават 0, другите —— 1) 9 000a CC5052 XORL2 R0,R2 # R2 ^= R0 (" " " " " " " " " " ") 10 000d C85251 BISL2 R2,R1 # R1 = R1 ^ R0 | R2 ^ R0 ( " " " " " " ") 11 0010 D02052 MOVL $32,R2 # Зареди брояча на битове 12 0013 D05250 MOVL R2,R0 # и брояча на лог. нули (остава си 32, ако R2 е нула) 13 0016 C05151 L1: ADDL2 R1,R1 # Изведи поредния бит в преноса 14 0019 D90050 SBWC $0,R0 # Преброй поредния бит като несъвпадащ, ако е лог. 1 15 001c F552F7 SOBGTR R2,L1 # Повтори 32 пъти 16 001f 04 RET # R0 = брой на лог. нули, т.е. на съвпадащите битове ==> we32k/nsamebit.s <== # Return in register %r0 the number of the coincident bits on the same position # in the words, passed in ap(0) -> r0, ap(4), and ap(8). section .text .globl nsamebit nsamebit() nsamebit: 0: 84 5a 40 MOVW 0(%ap),%r0 3: f4 40 74 41 XORW3 %r0,4(%ap),%r1# r1 = r0 ^ ap(4) (coincident bits 0, the rest 1) 7: f4 40 78 42 XORW3 %r0,8(%ap),%r2# r2 = r0 ^ ap(8) ( " " " " " " " ) b: b0 42 41 ORW2 %r2,%r1 # r1 = r0 ^ ap(4) | r0 ^ ap(8) (" " " " " " ) e: 88 41 41 MCOMW %r1,%r1 # Make the coincident bits log. 1, non-coincident - 0 11: 80 40 CLRW %r0 # Initialise the counter of the logical ones 13: cc 00 1f 41 42 L1: EXTFW &0,&31,%r1,%r2 # Save the highmost bit before shifting the rest 18: 9c 42 40 ADDW2 %r2,%r0 # Count the next bit as coincident, if it's logical one 1b: d0 01 41 41 LLSW3 &1,%r1,%r1 1f: 77 f4 BNEB L1 # Repeat while there are still logical ones in r1 21: 08 RET # r0 = number of log.ones in r1 (i.e., coincident bits) 22: 70 NOP 23: 70 NOP 68K GAS nsamebit.s page 1 1 | Да се напише подпрограма, която да връща в регистър D0 броя на съвпадащите 2 | битове на една и съща позиция в думите, подадени в SP(4,8,12) -> D0, D1 и D2. 3 4 .global nsamebit 5 nsamebit: 6 0000 4E56 0000 LINK %FP,#0 | Създай стекова рамка 7 0004 48E7 3000 MOVEML %D2-%D3,-(%SP) | GCC изисква D2 и следващите да се съхраняват 8 0008 4CEE 0007 0008 MOVEML 8(%FP),%D0-%D2 | Аргументите в регистри 9 000e B181 EORL %D0,%D1 | D1 ^= D0 (съвпадащите битове стават 0, другите —— 1) 10 0010 B182 EORL %D0,%D2 | D2 ^= D0 (" " " " " " " " " " ") 11 0012 8282 ORL %D2,%D1 | D1 = D1 ^ D0 | D2 ^ D0 ( " " " " " " ") 12 0014 741F MOVEQ #31,%D2 | Зареди брояча на битове 13 0016 7020 MOVEQ #32,%D0 | и брояча на лог. нули (остава си 32, ако D2 е нула) 14 0018 4283 CLRL %D3 15 001a E389 L1: LSLL #1,%D1 | Изведи поредния бит в преноса 16 001c 9183 SUBXL %D3,%D0 | Преброй поредния бит като несъвпадащ, ако е лог. 1 17 001e 51CA FFFA DBF %D2,L1 | Повтори 32 пъти 18 0022 4CDF 000C MOVEML (%SP)+,%D2-%D3 19 0026 4E5E UNLK %FP 20 0028 4E75 RTS | D0 = брой на лог. нули, т.е. на съвпадащите битове x86 NASM nsamebit.s 1 ; Да се напише подпрограма, която да връща в регистър EAX броя на съвпадащите 2 ; битове на една и съща позиция в думите, подадени в регистри EAX, EDX и ECX. 3 4 section .text 5 global nsamebit,_nsamebit; в GCC декларирай с __attribute__((regparm(3))) 6 nsamebit: 7 _nsamebit: 8 00000000 31C2 XOR EDX,EAX ; EDX ^= EAX (съвпадащите битове стават 0, другите – 1) 9 00000002 31C1 XOR ECX,EAX ; ECX ^= EAX ( " " " " " " " " " " ) 10 00000004 09CA OR EDX,ECX ; EDX = EDX ^ EAX | ECX ^ EAX (" " " " " " ) 11 00000006 F7D2 NOT EDX ; Направи съвпадащите битове лог. 1, а другите – лог. 0 12 00000008 F30FB8C2 POPCNT EAX,EDX ; Преброй съвпадащите битове 13 0000000C C3 RET ; и върни броя им в EAX ARM GAS nsamebit.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 броя на съвпадащите 2 // битове на една и съща позиция в думите, подадени в регистри R0, R1 и R2. 3 4 .global nsamebit 5 nsamebit: 6 0000 001021E0 EOR R1,R1,R0// R1 ^= R0 (съвпадащите битове стават 0, другите —— 1) 7 0004 002022E0 EOR R2,R2,R0// R2 ^= R0 (" " " " " " " " " " ") 8 0008 021081E1 ORR R1,R1,R2// R1 = R1 ^ R0 | R2 ^ R0 ( " " " " " " ") 9 000c 2000A0E3 MOV R0,#32 // Инициализирай изваждащия брояч на лог. единици 10 0010 011091E0 L1: ADDS R1,R1,R1// Изведи поредния бит в преноса 11 0014 01004022 SUBCS R0,R0,#1// Преброй поредния бит като несъвпадащ, ако е лог. 1 12 0018 FCFFFF1A BNE L1 // Повтаряй, докато има още останали лог. единици в R1 13 001c 1EFF2FE1 BX LR // R0 = брой лог. единици в R1 (т.е. съвпадащи битове) ARC GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър r0 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри r0, r1 и r2. 3 4 .global nsamebit 5 nsamebit: 6 0000 0779 XOR_S r1,r1,r0 # r1 ^= r0 (съвпадащите битове стават 0, другите —— 1) 7 0002 077A XOR_S r2,r2,r0 # r2 ^= r0 (" " " " " " " " " " ") 8 0004 4579 OR_S r1,r1,r2 # r1 = r1 ^ r0 | r2 ^ r0 ( " " " " " " ") 9 0006 20D8 MOV_S r0,32 # Инициализирай изваждащия брояч на лог. единици 10 0008 2F21 4080 L1: ASL.F r1,r1 # Изведи поредния бит в преноса 11 000c 4320 0000 SBC r0,r0,0 # Преброй поредния бит като несъвпадащ, ако е лог. 1 12 0010 FCF5 BNE_S L1 # Повтаряй, докато има още останали лог. единици в r1 13 0012 E07E J_S [blink] # r0 = брой лог. единици в r1 (т.е. съвпадащи битове) PPC GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър r3 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри r3, r4 и r5. 3 4 .global nsamebit 5 nsamebit: 6 0000 7C841A78 xor r4,r4,r3# r4 ^= r3 (съвпадащите битове стават 0, другите —— 1) 7 0004 7CA51A78 xor r5,r5,r3# r5 ^= r3 (" " " " " " " " " " ") 8 0008 7C8428F8 nor r4,r4,r5# r4 = ~(r4 ^ r3 | r5 ^ r3) " " " 1," " " 0) 9 000c 38600000 li r3,0 # Инициализирай брояча на лог. единици 10 0010 7C842015 L1: addc. r4,r4,r4# Изведи поредния бит в преноса 11 0014 7C630194 addze r3,r3 # Преброй поредния бит като съвпадащ, ако е лог. 1 12 0018 4082FFF8 bne L1 # Повтаряй, докато има още останали лог. единици в r4 13 001c 4E800020 blr # r3 = брой лог. единици в r4 (т.е. съвпадащи битове) SPARC GAS nsamebit.s page 1 1 ! Да се напише подпрограма, която да връща в регистър %o0 броя на съвпадащите 2 ! битове на една и съща позиция в думите, подадени в регистри %o0, %o1 и %o2. 3 4 .global nsamebit 5 nsamebit: 6 0000 921A0009 xor %o0,%o1,%o1!%o1 ^= %o0 (съвпадащите битове стават 0, другите 1) 7 0004 941A000A xor %o0,%o2,%o2!%o2 ^= %o0 (" " " " " " " " " " ) 8 0008 9212400A or %o1,%o2,%o1!%o1 = %o1 ^ %o0 | %o2 ^ %o0 ( " " " " " ) 9 000c 923A4000 not %o1 ! Направи съвпадащите битове лог. 1, несъвпадащите – 0 10 0010 90100000 clr %o0 ! Инициализирай брояча на лог. единици 11 0014 92824009 L1: addcc %o1,%o1,%o1! Изведи поредния бит в преноса 12 0018 90422000 addx %o0,0,%o0 ! Преброй поредния бит като съвпадащ, ако е лог. 1 13 001c 12BFFFFE bne L1 ! Повтаряй, докато има още останали лог. единици в %o1 14 0020 01000000 nop ! %o0 = брой лог. единици в %o1 (т.е. съвпадащи битове) 15 0024 81C3E008 retl 16 0028 01000000 nop MIPS GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър $2 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри $4, $5 и $6. 3 4 .ent nsamebit 5 .global nsamebit 6 nsamebit: 7 0000 00A42826 XOR $5,$5,$4# $5 ^= $4 (съвпадащите битове стават 0, другите —— 1) 8 0004 00C43026 XOR $6,$6,$4# $6 ^= $4 (" " " " " " " " " " ") 9 0008 00A62827 NOR $5,$5,$6# $5 = ~($5 ^ $4 | $6 ^ $4) " " " 1," " " 0) 10 000c 24020000 LI $2,0 # Инициализирай брояча на лог. единици 11 0010 00A0302A L1: SLT $6,$5,$0# Съхрани най-старшия бит, преди да изместиш останалите 12 0014 00052840 SLL $5,$5,1 13 ADDU $2,$2,$6# Преброй поредния бит като съвпадащ, ако е бил лог. 1 14 0018 14A0FFFD 00461021 BNE $5,$0,L1# Повтаряй, докато има още останали лог. единици в $5 15 0020 03E00008 00000000 JR $31 # $2 = брой лог. единици в $5 (т.е. съвпадащи битове) 16 0028 00000000 00000000 .end nsamebit RISC-V GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър a0 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри a0, a1 и a2. 3 4 .global nsamebit 5 nsamebit: 6 0000 A98D XOR a1,a1,a0# a1 ^= a0 (съвпадащите битове стават 0, другите —— 1) 7 0002 298E XOR a2,a2,a0# a2 ^= a0 (" " " " " " " " " " ") 8 0004 D18D OR a1,a1,a2 9 0006 93C5F5FF NOT a1,a1 # a1 = ~(a1 ^ a0 | a2 ^ a0) " " " 1," " " 0) 10 000a 13050000 MV a0,x0 # Инициализирай брояча на лог. единици 11 000e 33A60500 L1: SLT a2,a1,x0# Съхрани най-старшия бит, преди да изместиш останалите 12 0012 8605 SLLI a1,a1,1 13 0014 3295 ADD a0,a0,a2# Преброй поредния бит като съвпадащ, ако е бил лог. 1 14 0016 E5FD BNEZ a1,L1 # Повтаряй, докато има още останали лог. единици в a1 15 0018 8280 RET # a0 = брой лог. единици в a1 (т.е. съвпадащи битове) Nios II GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри r4, r5 и r6. 3 4 .global nsamebit 5 nsamebit: 6 0000 3AF00A29 XOR r5,r5,r4# r5 ^= r4 (съвпадащите битове стават 0, другите —— 1) 7 0004 3AF00C31 XOR r6,r6,r4# r6 ^= r4 (" " " " " " " " " " ") 8 0008 3A308A29 NOR r5,r5,r6# r5 = ~(r5 ^ r4 | r6 ^ r4) " " " 1," " " 0) 9 000c 3A880500 MOV r2,r0 # Инициализирай брояча на лог. единици 10 0010 3A800C28 L1: CMPLT r6,r5,r0# Съхрани най-старшия бит, преди да изместиш останалите 11 0014 7A900A28 SLLI r5,r5,1 12 0018 3A888511 ADD r2,r2,r6# Преброй поредния бит като съвпадащ, ако е бил лог. 1 13 001c 1EFC3F28 BNE r5,r0,L1# Повтаряй, докато има още останали лог. единици в r5 14 0020 3A2800F8 RET # r2 = брой лог. единици в r5 (т.е. съвпадащи битове) Xtensa GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър a2 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри a2, a3 и a4. 3 4 .global nsamebit 5 nsamebit: 6 0000 203330 XOR a3,a3,a2# a3 ^= a2 (съвпадащите битове стават 0, другите —— 1) 7 0003 204430 XOR a4,a4,a2# a4 ^= a2 (" " " " " " " " " " ") 8 0006 403320 OR a3,a3,a4 9 0009 303060 NEG a3,a3 10 000c 0B33 ADDI a3,a3,-1# a3 = ~(a3 ^ a2 | a4 ^ a2) " " " 1," " " 0) 11 000e 0C02 MOVI a2,0 # Инициализирай брояча на лог. единици 12 0010 304F05 L1: EXTUI a4,a3,31,1#Запази най-старшия бит, преди да изместиш останалите 13 0013 F03311 SLLI a3,a3,1 14 0016 4A22 ADD a2,a2,a4# Преброй поредния бит като съвпадащ, ако е бил лог. 1 15 0018 5643FF BNEZ a3,L1 # Повтаряй, докато има още останали лог. единици в a3 16 001b 0DF0 RET # a2 = брой лог. единици в a3 (т.е. съвпадащи битове) 88K GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри r2, r2 и r3. 3 4 .global _nsamebit 5 0000 F4635002 _nsamebit: 6 0004 F4845002 xor r3,r3,r2 # r3 ^= r2 (съвпадащите битове стават 0, другите —— 1) 7 0008 F4635804 xor r4,r4,r2 # r4 ^= r2 (" " " " " " " " " " ") 8 000c F4605C03 or r3,r3,r4 # r3 = (r3 ^ r2 | r4 ^ r2) " " " 1," " " 0) 9 0010 F4405800 or.c r3,r0,r3 # Направи съвпадащите битове лог. 1, несъвпадащите – 0 10 0014 F4636103 or r2,r0,r0 # Инициализирай брояча на лог. единици 11 0018 F4426200 L1: addu.co r3,r3,r3 # Изведи поредния бит в преноса 12 001c E9A3FFFE addu.ci r2,r2,r0 # Преброй поредния бит като съвпадащ, ако е лог. 1 13 0020 F400C001 bcnd ne0,r3,L1# Повтаряй, докато има още останали лог. единици в r3 jmp r1 # r2 = брой лог. единици в r3 (т.е. съвпадащи битове) Or1k GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър R11 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри R3, R4 и R5. 3 4 .global nsamebit 5 nsamebit: 6 0000 E0832005 L.XOR R4,R3,R4 # R4 ^= R3 (съвпадащите битове стават 0, другите 1) 7 0004 E0A32805 L.XOR R5,R3,R5 # R5 ^= R3 ( " " " " " " " " " ) 8 0008 E0842804 L.OR R4,R4,R5 # R4 = R4 ^ R3 | R5 ^ R3 ( " " " " " " ) 9 000c AC84FFFF L.XORI R4,R4,-1 # Направи съвпадащите битове лог. 1, несъвпадащите – 0 10 0010 E1600004 L.OR R11,R0,R0# Инициализирай брояча на лог. единици 11 0014 E0842000 L1: L.ADD R4,R4,R4 # Изведи поредния бит в преноса 12 0018 E4040000 L.SFEQ R4,R0 # Има ли още останали лог. единици в R4? 13 001c 0FFFFFFE L.BNF L1 # Да – продължи цикъла (изпълнява се след „L.ADDC“!) 14 0020 E16B0001 L.ADDC R11,R11,R0 # (преброй поредния бит като съвпадащ, ако е лог. 1) 15 0024 44004800 L.JR LR # Не – R11 = брой лог. единици в R4 (съвпадащи битове) 16 0028 15000000 L.NOP 0 Xilinx MicroBlaze GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър R3 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри R5, R6 и R7. 3 4 .global nsamebit 5 nsamebit: 6 0000 0028C688 XOR R6,R6,R5 # R6 ^= R5 (съвпадащите битове стават 0, другите —— 1) 7 0004 0028E788 XOR R7,R7,R5 # R7 ^= R5 (" " " " " " " " " " ") 8 0008 0038C680 OR R6,R6,R7 # R6 = R6 ^ R5 | R7 ^ R5 ( " " " " " " ") 9 000c FFFFC6A8 XORI R6,R6,-1 # Направи съвпадащите битове лог. 1, несъвпадащите – 0 10 0010 00006080 OR R3,R0,R0 # Инициализирай брояча на лог. единици 11 0014 0030C600 L1: ADD R6,R6,R6 # Изведи поредния бит в преноса 12 0018 00006308 ADDC R3,R3,R0 # Преброй поредния бит като съвпадащ, ако е лог. 1 13 001c F8FF26BC BNEI R6,L1 # Повтаряй, докато има още останали лог. единици в R6 14 0020 08000FB6 RTSD R15,8 # R3 = брой лог. единици в R6 (т.е. съвпадащи битове) 15 0024 00000080 NOP HPPA GAS nsamebit.s page 1 1 ; Да се напише подпрограма, която да връща в регистър %R28 броя на съвпадащите 2 ; битове на една и съща позиция в думите, подадени в регистри %R26, %R25 и %R24 3 4 .text 5 .global nsamebit 6 nsamebit: 7 0000 0B590299 XOR %R25,%R26,%R25 ; R25 ^= R26 (съвпадащите битове стават 0) 8 0004 0B580298 XOR %R24,%R26,%R24 ; R24 ^= R26 ( " " " " " " " ) 9 0008 0B190259 OR %R25,%R24,%R25 ; R25 = R25 ^ R26 | R24 ^ R26 (" " " ) 10 000c 0B200999 UADDCM %R0,%R25,%R25 ; Направи съвпадащите битове лог. 1 11 0010 341C0000 LDI 0,%R28 ; Инициализирай брояча на лог. единици 12 0014 0B390619 L1: ADD %R25,%R25,%R25 ; Изведи поредния бит в преноса 13 0018 88193FED COMBF,= %R25,%R0,L1 ; Повтаряй, докато R25 ≠ 0 (изп.се след „ADDC“) 14 001c 081C071C ADDC %R28,%R0,%R28 ; Преброй поредния бит като съвпадащ, ако е 1 15 0020 E840C002 BV,N (%R2) ; R28 = брой лог.единици, т.е. съвпадащи битове 15 00000000 Renesas / SuperH SH GAS Little Endian nsamebit.s page 1 1 ! Да се напише подпрограма, която да връща в регистър D0 броя на съвпадащите 2 ! битове на една и съща позиция в думите, подадени в регистри R4, R5 и R6. 3 4 .global nsamebit 5 nsamebit: 6 0000 4A25 XOR R4,R5 ! R5 ^= R4 (съвпадащите битове стават 0, другите – 1) 7 0002 4A26 XOR R4,R6 ! R6 ^= R4 ( " " " " " " " " " " ) 8 0004 6B25 OR R6,R5 ! R5 = R5 ^ R4 | R6 ^ R4 (" " " " " " ) 9 0006 20E6 MOV #32,R6 ! Инициализирай брояча на битовете 10 0008 20E0 MOV #32,R0 ! и брояча на лог. нули (остава си 32, ако R5 е нула) 11 000a 00E4 MOV #0,R4 ! Подготви умалителя за изваждането с пренос 12 000c 0145 L1: SHLR R5 ! Изведи поредния бит в преноса 13 000e 4A30 SUBC R4,R0 ! Преброй поредния бит като несъвпадащ, ако е лог. 1 14 0010 1046 DT R6 ! Има ли още битове? 15 0012 FB8B BF L1 ! Да, продължи 16 0014 0B00 RTS ! Не, върни в R0 броя лог. нули, т.е. съвпадащи битове 17 0016 0900 NOP GAS for CRIS nsamebit.s page 1 1 ; Да се напише подпрограма, която да връща в регистър R10 броя на съвпадащите 2 ; битове на една и съща позиция в думите, подадени в регистри R10, R11 и R12. 3 4 .global nsamebit 5 nsamebit: 6 0000 BAB7 XOR $R10,$R11 ; R11 ^= R10 (съвпадащите битове стават 0, другите 1) 7 0002 BAC7 XOR $R10,$R12 ; R12 ^= R10 (" " " " " " " " " " ) 8 0004 6CB7 OR.D $R12,$R11 ; R11 = R11 ^ R10 | R12 ^ R10 ( " " " " " ) 9 0006 7B87 NOT $R11 ; Направи съвпадащите битове лог.1, несъвпадащите – 0 10 0008 7A86 CLEAR.D $R10 ; Инициализирай брояча на лог. единици 11 000a 7C86 CLEAR.D $R12 ; и константата за „ADDC“ 12 000c 2BB6 L1: ADD.D $R11,$R11 ; Изведи поредния бит в преноса 13 000e 7CA5 ADDC $R12,$R10 ; Преброй поредния бит като съвпадащ, ако е лог. 1 14 0010 C0B2 CMPQ 0,$R11 ; Има ли още останали лог. единици в R11? 15 0012 FB20 BNE L1 ; Да, продължи 16 0014 B005 NOP ; Не, R10 = брой лог.единици в R11 (съвпадащи битове) 17 0016 F0B9 RET 18 0018 B0050000 NOP BFIN GAS nsamebit.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 броя на съвпадащите 2 # битове на една и съща позиция в думите, подадени в регистри R0, R1 и R2. 3 4 .global _nsamebit 5 _nsamebit: 6 0000 4158 R1 = R1 ^ R0; # Съвпадащите битове стават 0, другите - 1 7 0002 8258 R2 = R2 ^ R0; # " " " " " " " " " " 8 0004 5156 R1 = R1 | R2; 9 0006 C943 R1 = ~R1; # " " " " " " 1, " " – 0, нулирай AC0 10 0008 0060 R0 = 0; # Инициализирай брояча на лог. единици 11 000a 0C03 L_1: CC = AC0; # Нулирай входящия пренос (AC0 си остава 0!), така че 12 000c 82C609C2 R1 = ROT R1 BY 1;# постепенно да запълни R1 с нули отдясно 13 0010 0202 R2 = CC; # Получи изходящия пренос 14 0012 1050 R0 = R0 + R2; # Преброй поредния бит като съвпадащ, 15 0014 0902 CC = R1; # ако е бил лог. 1 16 0016 FA1B IF CC JUMP L_1; # Повтаряй, докато има още останали лог. единици в R1 17 0018 10000000 RTS; # R0 = брой лог. единици в R1 (т.е. съвпадащи битове) Hexagon GAS nsamebit.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 броя на съвпадащите 2 // битове на една и съща позиция в думите, подадени в регистри R0, R1 и R2. 3 4 .global nsamebit 5 nsamebit: 6 0000 01C061F1 R1 = XOR(R1,R0)//R1 ^= R0 (съвпадащите битове стават 0, другите – 1) 7 0004 21C0C2EF R1 |= XOR(R2,R0)//R1 = R1 ^ R0 | R2 ^ R0 (" " " " " " " ) 8 { R0 = NOT(R1) // Направи съвпадащите битове лог. 1, несъвпадащите – 0 9 0008 E07F6176 01C00078 R1 = #0 } // Нулирай старшата дума, за да се преброят логическите 10 { R0 = POPCOUNT(R1:0)// единици само в младшата и ги преброй 11 0010 60406088 00C09F52 JUMPR LR } // R0 = брой съвпадащи битове S/390 GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да обръща огледално битовете на двойната 2 # дума в регистри 2:3. 3 4 .global bitrev64 5 bitrev64: 6 0000 A7580001 LHI 5,1 # Подготви маска за най-старшия бит 7 0004 8950001F SLL 5,31 # (LARL е неизползваема – адресите са 31 бита!) 8 0008 A7480020 LHI 4,32 # Инициализирай брояча на битове 9 000c 1802 LR 0,2 # Старша дума 10 000e 1405 NR 0,5 # Отдели най-старшия бит в регистър 0 11 0010 89200001 SLL 2,1 # Направи място за най-младшия бит в ст. дума 12 0014 A7180001 L1: LHI 1,1 # Подготви маска за най-младшия бит 13 0018 1413 NR 1,3 # и го отдели в регистър 1 14 001a 88300001 SRL 3,1 # Направи място за най-старшия бит 15 001e 1630 OR 3,0 # и го въведи в младшата дума 16 0020 1802 LR 0,2 17 0022 1405 NR 0,5 # Отдели най-старшия бит 18 0024 89200001 SLL 2,1 # Направи място за най-младшия бит 19 0028 1621 OR 2,1 # и го въведи в старшата дума 20 002a A746FFF5 BRCT 4,L1 # Следваща итерация на цикъла 21 002e 07FE BR 14 # Върни новата стойност ==> id32/bitrev64.s 1 * Reverse the order of the bits of the double word in *7(0):*7(4) -> reg. 0:1 2 3 entry bitrev64 00000000d 4 bitrev64 equ * 00000d 5857 0000 5 l 5,0(7) Address of the double word 00004d 5805 0000 6 l 0,0(5) High word 00008d 5815 0004 7 l 1,4(5) Low word 0000Cd C840 0020 8 lhi 4,32(0) Initialise the bit counter 00010d 0820 9 lr 2,0 High word 00012d F420 8000 0000 10 ni 2,x'80000000'(0) Isolate the highmost bit in register 2 00018d 1101 11 slls 0,1 Make room for the lowmost bit in the high word 0001Ad 0831 12 L1 lr 3,1 Low word 0001Cd C430 0001 13 ni 3,1(0) Isolate the lowmost bit in register 3 00020d 1011 14 srls 1,1 Make room for the highmost bit 00022d 0612 15 or 1,2 and put it in the low word 00024d 0820 16 lr 2,0 00026d F420 8000 0000 17 ni 2,x'80000000'(0) Isolate the highmost bit 0002Cd 1101 18 slls 0,1 Make room for the lowmost bit 0002Ed 0603 19 or 0,3 and put it in the high word 00030d 2741 20 sis 4,1 If there are more bits, 00032d 203C 0000001Ad 21 bnzs L1 go to the next loop iteration 00034d 5005 0000 22 st 0,0(5) Write the new value - high 00038d 5015 0004 23 st 1,4(5) and low word 0003Cd 030F 24 br 15 Return to the calling function VAX GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да връща в регистри R1:R0 двойната дума в 2 # AP(8):AP(4) с огледално обърнати битове. 3 4 .global _bitrev64 5 _bitrev64: 6 0000 1C00 .word 0x1C # R2-R4 7 0002 7DAC0452 MOVQ 4(AP),R2 # R3 = старшата дума, R2 = младшата 8 0006 D01F54 MOVL $31,R4 # Инициализирай брояча на битове 9 0009 F0535401 50 L1: INSV R3,R4,$1,R0 # Копирай 1 бит на старшата дума в младшата 10 000e F0525401 51 INSV R2,R4,$1,R1 # " " " " младшата " " старшата 11 0013 798FFF52 52 ASHQ $-1,R2,R2 # Подготви по 1 нов най-младши бит на R2 и R3 12 0018 F454EE SOBGEQ R4,L1 # Следваща итерация на цикъла 13 001b 04 RET ==> we32k/bitrev64.s <== # Reverse the order of the bits of the double word in ap(0):ap(4) -> r0:r1 section .text .globl bitrev64 bitrev64() bitrev64: 0: 10 47 SAVE %r7 #"AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 47 MOVW 0(%ap),%r7 # Programming Manual", pp. 6-13,6-14: save r7-8 5: 84 74 48 MOVW 4(%ap),%r8 # r7 = high word, r8 = low word 8: 87 1f 41 MOVB &31,%r1 # Initialise the bit counter b: cc 00 1f 48 42 EXTFW &0,&31,%r8,%r2 # Save low word's highmost bit as a lowmost one 10: 84 47 40 MOVW %r7,%r0 # as well as the entire high word 13: c8 00 00 48 40 L1: INSFW &0,&0,%r8,%r0 # Copy the lowmost bit of the low word 18: d4 01 48 48 LRSW3 &1,%r8,%r8 # Right-shift the low word 1c: d8 1f 40 40 ROTW &31,%r0,%r0 # Rotate the high word left by 1 bit 20: c8 00 1f 40 48 INSFW &0,&31,%r0,%r8 # Put the former highmost bit of the high word 25: 97 41 DECB %r1 # If there are more bits, 27: 77 ec BNEB L1 # go to the next loop iteration 29: d4 01 48 41 LRSW3 &1,%r8,%r1 # Right-shift the low word 2d: c8 00 1f 47 41 INSFW &0,&31,%r7,%r1 # Copy the lowmost bit as the highmost 32: c8 00 00 42 40 INSFW &0,&0,%r2,%r0 # and the highmost bit as the lowmost 37: 04 c9 f0 4c MOVAW -16(%fp),%sp RESTORE %r7 # Restore the saved registers (r7-8) 3b: 20 48 POPW %r8 3d: 20 47 POPW %r7 3f: 20 49 POPW %fp 41: 08 RET 42: 70 NOP 43: 70 NOP 68K GAS bitrev64.s page 1 1 | Да се напише подпрограма, която да връща в регистри D0:D1 двойната дума в 2 | SP(4):SP(8) с огледално обърнати битове. 3 4 .global bitrev64 5 bitrev64: 6 0000 4CEF 0003 0004 MOVEML 4(%SP),%D0-%D1 | D0 = старша дума, D1 = младша дума 7 0006 2F02 MOVEL %D2,-(%SP) | GCC изисква D2 да се съхранява 8 0008 741F MOVEQ #31,%D2 | Инициализирай брояча на битове 9 000a E389 LSLL #1,%D1 | Изведи най-старшия бит в X 10 000c E290 L1: ROXRL #1,%D0 | Въведи най-старшия бит от X, изведи там най-младшия 11 000e E391 ROXLL #1,%D1 | Въведи най-младшия бит от X, изведи там най-старшия 12 0010 51CA FFFA DBF %D2,L1 | Следваща итерация на цикъла 13 0014 241F MOVEL (%SP)+,%D2 14 0016 4E75 RTS x86 NASM bitrev64.s 1 ; Да се напише подпрограма, която да обръща огледално битовете на двойната 2 ; дума в регистри EDX:EAX. 3 4 section .text 5 global bitrev64,_bitrev64; в GCC декларирай с __attribute__((regparm(3))) 6 bitrev64: 7 _bitrev64: ; младшата дума се предава в EAX, старшата - в EDX 8 00000000 B920000000 MOV ECX,32 ; Инициализирай брояча на битове 9 00000005 D1E2 SHL EDX,1 ; Изведи най-старшия бит в CF 10 00000007 D1D8 L1: RCR EAX,1 ; Въведи най-старшия бит от CF, изведи там най-младшия 11 00000009 D1D2 RCL EDX,1 ; Въведи най-младшия бит от CF, изведи там най-старшия 12 0000000B E2FA LOOP L1 ; Следваща итерация на цикъла 13 0000000D C3 RET ARM GAS bitrev64.s page 1 1 // Да се напише подпрограма, която да обръща огледално битовете на двойната 2 // дума в регистри R1:R0. 3 4 .global bitrev64 5 bitrev64: 6 0000 0120A0E1 MOV R2,R1 7 0004 301FFFE6 RBIT R1,R0 8 0008 320FFFE6 RBIT R0,R2 9 000c 1EFF2FE1 BX LR 10 11 /* А ето как можеше да изглежда програмата, ако я нямаше командата RBIT: 12 13 MOV R2,#32 // Инициализирай брояча на битове 14 ADDS R1,R1,R1// Изведи най-старшия бит в C 15 L1: MOVS R0,R0,RRX//Въведи най-старшия бит от C, изведи там най-младшия 16 ADCS R1,R1,R1// Въведи най-младшия бит от C, изведи там най-старшия 17 SUB R2,R2,#1// Следваща итерация на цикъла? (Внимание: съхрани C!) 18 MULS R3,R2,R2// (ненулев ли е още броячът, респ. квадратът му?) 19 BNE L1 // Да, продължи 20 BX LR // Не, върни новата стойност 21 */ ARC GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да обръща огледално битовете на двойната 2 # дума в регистри r1:r0. 3 4 .global bitrev64 5 bitrev64: 6 0000 2F21 4080 ASL.F r1,r1 # Изведи най-старшия бит в C 7 0004 4A24 0078 MOV lp_count,32 # Задай брой итерации 8 0008 A820 8001 LP L1 # и край на цикъла 9 000c 2F20 0480 RRC.F r0,r0 # Въведи най-старшия бит от C, изведи там най-младшия 10 0010 2F21 4B80 RLC.F r1,r1 # Въведи най-младшия бит от C, изведи там най-старшия 11 0014 E07E L1: J_S [blink] PPC GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да обръща огледално битовете на двойната 2 # дума в регистри r3:r4. 3 4 .global bitrev64 5 bitrev64: 6 0000 38A0001F li r5,31 # Инициализирай брояча на битове 7 0004 7CA903A6 mtctr r5 8 0008 7C651B78 mr r5,r3 # Съхрани най-младшия бит на старшата дума 9 000c 50850000 rlwimi r5,r4,0,0,0 # и най-старшия бит на младшата дума 10 0010 508307FE L1: rlwimi r3,r4,0,31,31 # Копирай най-младшия бит на младшата дума 11 0014 5484F87E rlwinm r4,r4,31,1,31 # Измести надясно младшата дума 12 0018 50640000 rlwimi r4,r3,0,0,0 # Копирай най-старшия бит на старшата дума 13 001c 5463083C rlwinm r3,r3,1,0,30 # Измести наляво старшата дума 14 0020 4200FFF0 bdnz L1 # Следваща итерация на цикъла 15 0024 5484F87E rlwinm r4,r4,31,1,31 # Измести надясно младшата дума 16 0028 50A4F800 rlwimi r4,r5,31,0,0 # Копирай най-младшия бит като най-старши 17 002c 50A30FFE rlwimi r3,r5,1,31,31 # и най-старшия бит като най-младши 18 0030 4E800020 blr SPARC GAS bitrev64.s page 1 1 ! Да се напише подпрограма, която да обръща огледално битовете на двойната 2 ! дума в регистри %o0:%o1. 3 4 .global bitrev64 5 bitrev64: 6 0000 17200000 set 0x80000000,%o3 ! Подготви маска за най-старшия бит 7 0004 94102020 mov 32,%o2 ! Инициализирай брояча на битове 8 0008 980A000B and %o0,%o3,%o4 ! Отдели най-старшия бит в %o4 9 000c 912A2001 sll %o0,1,%o0 ! Направи място за най-младшия бит в ст. дума 10 0010 9A0A6001 L1: and %o1,1,%o5 ! Отдели най-младшия бит в %o5 11 0014 93326001 srl %o1,1,%o1 ! Направи място за най-старшия бит 12 0018 9212400C or %o1,%o4,%o1 ! и го въведи в младшата дума 13 001c 980A000B and %o0,%o3,%o4 ! Отдели най-старшия бит 14 0020 912A2001 sll %o0,1,%o0 ! Направи място за най-младшия бит 15 0024 9012000D or %o0,%o5,%o0 ! и го въведи в старшата дума 16 0028 94A2A001 deccc %o2 ! Следваща итерация на цикъла? 17 002c 12BFFFF9 bne L1 ! Да, продължи 18 0030 01000000 nop ! Не, върни новата стойност 19 0034 81C3E008 retl 20 0038 01000000 nop MIPS GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да връща в регистри $2:$3 двойната дума в 2 # регистри $4:$5 с огледално обърнати битове. 3 4 .ent bitrev64 5 .global bitrev64 6 bitrev64: 7 0000 2403001F LI $3,31 # Инициализирай брояча на битове 8 0004 7CA707C0 EXT $7,$5,31,1 # Съхрани най-старшия бит на младшата дума като 9 0008 00801021 MOVE $2,$4 # най-младши, както и цялата старша дума 10 000c 7CA20004 L1: INS $2,$5,0,1 # Копирай най-младшия бит на младшата дума 11 0010 00052842 SRL $5,$5,1 # Измести надясно младшата дума 12 0014 002217C2 ROTR $2,$2,31 # Завърти с 1 бит наляво старшата дума 13 0018 7C45FFC4 INS $5,$2,31,1 # Запиши бившия най-старши бит на старшата дума 14 001c 2463FFFF ADDIU $3,-1 # Ако има още битове, 15 0020 1460FFFA 00000000 BNE $3,$0,L1 # премини към следващата итерация на цикъла 16 0028 00051842 SRL $3,$5,1 # Измести надясно младшата дума 17 002c 7C83FFC4 INS $3,$4,31,1 # Копирай най-младшия бит като най-старши 18 INS $2,$7,0,1 # и най-старшия бит като най-младши 19 0030 03E00008 7CE20004 JR $31 20 0038 00000000 00000000 .end bitrev64 RISC-V GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да обръща огледално битовете на двойната 2 # дума в регистри a1:a0 3 4 .global bitrev64 5 bitrev64: 6 0000 B7060080 LUI a3,1 << (31 - 12) # Подготви маска за най-старшия бит 7 0004 13060002 LI a2,32 # Инициализирай брояча на битове 8 0008 33F7D500 AND a4,a1,a3 # Отдели най-старшия бит в a4 9 000c 8605 SLLI a1,a1,1 # Направи място за най-младшия бит в ст. дума 10 000e 93771500 L1: AND a5,a0,1 # Отдели най-младшия бит в a5 11 0012 0581 SRLI a0,a0,1 # Направи място за най-старшия бит 12 0014 598D OR a0,a0,a4 # и го въведи в младшата дума 13 0016 33F7D500 AND a4,a1,a3 # Отдели най-старшия бит 14 001a 8605 SLLI a1,a1,1 # Направи място за най-младшия бит 15 001c DD8D OR a1,a1,a5 # и го въведи в старшата дума 16 001e 7D16 ADDI a2,a2,-1 # Следваща итерация на цикъла? 17 0020 7DF6 BNEZ a2,L1 # Да, продължи 18 0022 8280 RET # Не, върни новата стойност Nios II GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да връща в регистри r3:r2 двойната дума в 2 # регистри r5:r4 с огледално обърнати битове. 3 4 .global bitrev64 5 bitrev64: 6 0000 3400E001 MOVHI r7,1 << (31 - 16) # Подготви маска за най-старшия бит 7 0004 14088001 MOVUI r6,32 # Инициализирай брояча на битове 8 0008 3A70D029 AND r8,r5,r7 # Отдели най-старшия бит в r8 9 000c 7A900A28 SLLI r5,r5,1 # Направи място за най-младшия бит в ст. дума 10 0010 4C004022 L1: ANDI r9,r4,1 # Отдели най-младшия бит в r9 11 0014 7AD00820 SRLI r4,r4,1 # Направи място за най-старшия бит 12 0018 3AB00822 OR r4,r4,r8 # и го въведи в младшата дума 13 001c 3A70D029 AND r8,r5,r7 # Отдели най-старшия бит 14 0020 7A900A28 SLLI r5,r5,1 # Направи място за най-младшия бит 15 0024 3AB04A2A OR r5,r5,r9 # и го въведи в старшата дума 16 0028 C4FFBF31 SUBI r6,r6,1 # Следваща итерация на цикъла? 17 002c 1EF83F30 BNE r6,r0,L1 # Да, продължи 18 0030 3A880520 MOV r2,r4 # Не, върни новата стойност в r3:r2 19 0034 3A880728 MOV r3,r5 20 0038 3A2800F8 RET Xtensa GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да обръща огледално битовете на двойната 2 # дума в регистри a3:a2 3 4 .global bitrev64 5 bitrev64: 6 0000 510000 MOVI a5,1 << 31 # Подготви маска за най-старшия бит 7 0003 506310 AND a6,a3,a5 # Отдели най-старшия бит в a6 8 0006 F03311 SLLI a3,a3,1 # Направи място за най-младшия бит в ст. дума 9 0009 2C04 MOVI a4,32 # Задай брой итерации, 10 000b 3DF07684 11 LOOP a4,L1 # начален и краен адрес на цикъла 11 0010 207004 EXTUI a7,a2,0,1 # Отдели най-младшия бит в a5 12 0013 202141 SRLI a2,a2,1 # Направи място за най-старшия бит 13 0016 602220 OR a2,a2,a6 # и го въведи в младшата дума 14 0019 506310 AND a6,a3,a5 # Отдели най-старшия бит 15 001c F03311 SLLI a3,a3,1 # Направи място за най-младшия бит 16 001f 703320 OR a3,a3,a7 # и го въведи в старшата дума 17 0022 0DF0 L1: RET # Върни новата стойност 88K GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да обръща огледално битовете на двойната 2 # дума в регистри r2:r3. 3 4 .global _bitrev64 5 0000 58800020 _bitrev64: 6 0004 4CA28000 or r4,r0,32 # Инициализирай брояча на битове 7 0008 F042A001 mask.u r5,r2,0x8000 # Отдели най-старшия бит в r5 8 000c 48C30001 mak r2,r2,0<1> # Направи място за най-младшия бит в ст. дума 9 0010 F0639801 L1: mask r6,r3,1 # Отдели най-младшия бит в r6 10 0014 F4635805 extu r3,r3,0<1> # Направи място за най-старшия бит 11 0018 4CA28000 or r3,r3,r5 # и го въведи в младшата дума 12 001c F042A001 mask.u r5,r2,0x8000 # Отдели най-старшия бит 13 0020 F4425806 mak r2,r2,0<1> # Направи място за най-младшия бит 14 0024 64840001 or r2,r2,r6 # и го въведи в старшата дума 15 0028 E9A4FFF9 subu r4,r4,1 # Следваща итерация на цикъла? 16 002c F400C001 bcnd ne0,r4,L1 # Да, продължи jmp r1 # Не, върни новата стойност Or1k GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да връща в регистри R11:R12 двойната дума в 2 # регистри R3:R4 с огледално обърнати битове. 3 4 .global bitrev64 5 bitrev64: 6 0000 18C08000 L.MOVHI R6,0x8000 # Подготви маска за най-старшия бит 7 0004 A8A00020 L.ORI R5,R0,32 # Инициализирай брояча на битове 8 0008 E0E33003 L.AND R7,R3,R6 # Отдели най-старшия бит в R7 9 000c B8630001 L.SLLI R3,R3,1 # Направи място за най-младшия бит в ст. дума 10 0010 A5040001 L1: L.ANDI R8,R4,1 # Отдели най-младшия бит в R8 11 0014 B8840041 L.SRLI R4,R4,1 # Направи място за най-старшия бит 12 0018 E0843804 L.OR R4,R4,R7 # и го въведи в младшата дума 13 001c E0E33003 L.AND R7,R3,R6 # Отдели най-старшия бит 14 0020 B8630001 L.SLLI R3,R3,1 # Направи място за най-младшия бит 15 0024 E0634004 L.OR R3,R3,R8 # и го въведи в старшата дума 16 0028 9CA5FFFF L.ADDI R5,R5,-1 # Обнови брояча на итерации 17 002c E4050000 L.SFEQ R5,R0 # Следваща итерация на цикъла? 18 0030 0FFFFFF8 L.BNF L1 # Да, продължи 19 0034 E1630004 L.OR R11,R3,R0 # Не, върни новата стойност в R11:R12 20 0038 44004800 L.JR LR # Последните „L.OR“ се изпълняват преди 21 003c E1840004 L.OR R12,R4,R0 # прехода, след който се намират Xilinx MicroBlaze GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да връща в регистри R4:R3 двойната дума в 2 # регистри R6:R5 с огледално обърнати битове. 3 4 .global bitrev64 5 bitrev64: # младшата дума се предава в R5, старшата - в R6 6 0000 2000E0A0 ORI R7,R0,32# Инициализирай брояча на битове 7 0004 0030C600 ADD R6,R6,R6# Изведи най-старшия бит в C 8 0008 2100A590 L1: SRC R5,R5 # Въведи най-старшия бит от C, изведи там най-младшия 9 000c 0030C608 ADDC R6,R6,R6# Въведи най-младшия бит от C, изведи там най-старшия 10 0010 FFFFE730 ADDIK R7,R7,-1# Следваща итерация на цикъла? 11 0014 F4FF27BC BNEI R7,L1 # Да, продължи 12 0018 00006580 OR R3,R5,R0# Не, новата стойност трябва да се върне в R4:R3 13 001c 08000FB6 RTSD R15,8 # Върни управлението 14 0020 00008680 OR R4,R6,R0# Изпълнява се преди „RTSD“! HPPA GAS bitrev64.s page 1 1 ; Да се напише подпрограма, която да връща в регистри %R28:%R29 двойната дума в 2 ; %R25:%R26 с огледално обърнати битове. 3 4 .text 5 .global bitrev64 6 bitrev64: 7 0000 3418003E LDI 31,%R24 ; Инициализирай брояча на битове 8 0004 D3390819 L1: SHD %R25,%R25,31,%R25; Подготви 1 нов най-младши бит на R25 9 0008 D35A081A SHD %R26,%R26,31,%R26; " " " " " " " " R26 10 000c 01781840 MTSAR %R24 ; Обнови позицията на бита за копиране 11 0010 D7B9041F VDEP %R25,1,%R29 ; Копирай 1 бит на старшата дума в младшата 12 0014 AF1F5FD5 ADDIBF,< -1,%R24,L1 ; Следваща итерация (изпълнява се след „VDEP“) 13 0018 D79A041F VDEP %R26,1,%R28 ; Копирай 1 бит на младшата дума в старшата 14 001c E840C002 BV,N (%R2) Renesas / SuperH SH GAS Little Endian bitrev64.s page 1 1 ! Да се напише подпрограма, която да връща в регистри R1:R0 двойната дума в 2 ! регистри R5:R4 с огледално обърнати битове. 3 4 .global bitrev64 5 bitrev64: ! младшата дума се предава в R4, старшата - в R5 6 0000 20E2 MOV #32,R2 ! Инициализирай брояча на битовете 7 0002 0144 L1: SHLR R4 ! Изведи най-младшия бит от старата младша дума в T 8 0004 2441 ROTCL R1 ! Въведи най-младшия бит от T в новата старша дума 9 0006 0145 SHLR R5 ! Изведи най-младшия бит от старата старша дума в T 10 0008 2440 ROTCL R0 ! Въведи най-младшия бит от T в новата младша дума 11 000a 1042 DT R2 ! Има ли още битове? 12 000c F98B BF L1 ! Да, продължи 13 000e 0B00 RTS ! Не, върни младшата дума в R0, а старшата – в R1 14 0010 0900 NOP GAS for CRIS bitrev64.s page 1 1 ; Да се напише подпрограма, която да обръща огледално битовете на двойната 2 ; дума в регистри R11:R10. 3 4 .global bitrev64 5 bitrev64: 6 0000 7A77 SWAPWBR $R10 7 0002 7B77 SWAPWBR $R11 ; Обърни огледално битовете в R10 и R11 8 0004 BBA7 XOR $R11,$R10 ; и размени съдържанието им 9 0006 BAB7 XOR $R10,$R11 10 0008 F0B9 RET 11 000a BBA7 XOR $R11,$R10 ; Изпълнява се преди „RET“ 12 13 /* А ето как можеше да изглежда програмата, ако я нямаше командата „SWAP“: 14 15 MOVE.D 0x80000000,$R13 ; Подготви маска за най-старшия бит 16 MOVEQ 31,$R12 ; Инициализирай брояча на битове (32 не може) 17 MOVE.D $R11,$R15 ; Старша дума 18 AND.D $R13,$R15 ; Отдели най-старшия бит в R15 19 LSLQ 1,$R11 ; Направи място за най-младшия бит в ст. дума 20 L1: MOVEQ 1,$R9 ; Подготви маска за най-младшия бит 21 AND.D $R10,$R9 ; и го отдели в R9 22 LSRQ 1,$R10 ; Направи място за най-старшия бит 23 OR.D $R15,$R10 ; и го въведи в младшата дума 24 MOVE.D $R11,$R15 25 AND.D $R13,$R15 ; Отдели най-старшия бит 26 LSLQ 1,$R11 ; Направи място за най-младшия бит 27 OR.D $R9,$R11 ; и го въведи в старшата дума 28 SUBQ 1,$R12 ; Следваща итерация на цикъла 29 BCC L1 30 NOP 31 RET ; Върни новата стойност 32 NOP 33 */ BFIN GAS bitrev64.s page 1 1 # Да се напише подпрограма, която да обръща огледално битовете на двойната 2 # дума в регистри R1:R0. 3 4 .global _bitrev64 5 _bitrev64: # Младшата дума се предава в R0, старшата - в R1 6 0000 82C609C2 R1 = ROT R1 BY 1;#Изведи най-старшия бит в CC (новият бит 0 не е важен) 7 0004 0069 P0 = 32; # Задай брой итерации, начало и край на цикъла 8 0006 A2E00400 LSETUP (L_1, L_2) LC0 = P0; 9 000a 82C6F8C1 L_1: R0 = ROT R0 BY -1;#Въведи най-старшия бит от CC, изведи там най-младшия 10 000e 82C609C2 L_2: R1 = ROT R1 BY 1;# Въведи най-младшия бит от CC, изведи там най-старшия 11 0012 1000 RTS; Hexagon GAS bitrev64.s page 1 1 // Да се напише подпрограма, която да обръща огледално битовете на двойната 2 // дума в регистри R1:R0. 3 4 .global bitrev64 5 bitrev64: 6 { R1:0 = BREV(R1:0) 7 0000 C040C080 00C09F52 JUMPR LR } S/390 GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 C0400000 0026 LARL 4,WGHTS 6 0006 A718000A LHI 1,10 7 000a 1700 XR 0,0 8 000c 1733 XR 3,3 9 000e 1755 XR 5,5 10 0010 43302000 L1: IC 3,0(2) 11 0014 A72A0001 AHI 2,1 12 0018 A73AFFD0 AHI 3,-'0' 13 001c 43004000 IC 0,0(4) 14 0020 A74A0001 AHI 4,1 15 0024 A71AFFFF AHI 1,-1 16 0028 A7840007 JE L2 17 002c B2520003 MSR 0,3 18 0030 1E50 ALR 5,0 19 0032 A7F4FFEF J L1 20 0036 1744 L2: XR 4,4 21 0038 B9970040 DLR 4,0 22 003c A74E000A CHI 4,10 23 0040 A7740003 JNE L3 24 0044 1744 XR 4,4 25 0046 1F43 L3: SLR 4,3 26 0048 1824 LR 2,4 27 004a 07FE BR 14 28 004c 02040805 0A090703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 28 060B0707 ==> id32/ucnvrf.s <== 1 * Guess what this subroutine does: 2 3 entry ucnvrf 00000000d 4 ucnvrf equ * 00000d 5827 0000 5 l 2,0(7) 00004d E640 8028 00000030d 6 la 4,WGHTS(0) 00008d 241A 7 lis 1,10 0000Ad 0700 8 xr 0,0 0000Cd D332 0000 9 L1 lb 3,0(2) 00010d 2621 10 ais 2,1 00012d CB30 0030 11 shi 3,c'0' 00016d D354 0000 12 lb 5,0(4) 0001Ad 2641 13 ais 4,1 0001Cd 2711 14 sis 1,1 0001Ed 2334 00000026d 15 bzs L2 00020d 0C35 16 mhr 3,5 00022d 0A03 17 ar 0,3 00024d 220C 0000000Cd 18 bs L1 00026d 0D05 19 L2 dhr 0,5 00028d 245A 20 lis 5,10 0002Ad 0D05 21 dhr 0,5 0002Cd 0B03 22 sr 0,3 0002Ed 030F 23 br 15 00030d 0204 0805 0A09 0703 24 WGHTS db 2,4,8,5,10,9,7,3,6,11 060B 24 VAX GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global _ucnvrf 4 _ucnvrf: 5 0000 3C00 .word 0x3C 6 0002 D0AC0450 MOVL 4(AP),R0 7 0006 D08F2B00 000051 MOVL $WGHTS-1,R1 8 000d FD7D0A52 MOVO $10,R2 9 0011 848153 L1: MULB2 (R1)+,R3 10 0014 C05354 ADDL2 R3,R4 11 0017 83308053 SUBB3 $'0',(R0)+,R3 12 001b F552F3 SOBGTR R2,L1 13 001e 7B0B5450 54 EDIV $11,R4,R0,R4 14 0023 7B0A5451 50 EDIV $10,R4,R1,R0 15 0028 C25350 SUBL2 R3,R0 16 002b 04 RET 17 002c 02040805 0A090703 06010101 WGHTS: .byte 2,4,8,5,10,9,7,3,6 ==> we32k/ucnvrf.s <== # Guess what this subroutine does: section .text .globl ucnvrf ucnvrf() ucnvrf: 0: 10 47 SAVE %r7 2: 84 5a 47 MOVW 0(%ap),%r7 5: 84 4f 44 00 00 00 48 MOVW &WGHTS,%r8 c: 80 42 CLRW %r2 e: 87 57 41 L1: MOVB (%r7),%r1 11: 70 NOP 12: 90 47 INCW %r7 14: bf 30 41 SUBB2 &0x30,%r1 17: 87 58 40 MOVB (%r8),%r0 1a: 70 NOP 1b: 90 48 INCW %r8 1d: 3c 4f 4e 00 00 00 48 CMPW &WGHTS+10,%r8 24: 53 0a BGEUB L2 26: a8 41 40 MULW2 %r1,%r0 29: 9c 40 42 ADDW2 %r0,%r2 2c: 7b e2 BRB L1 2e: a4 40 42 L2: MODW2 %r0,%r2 31: a4 0a 42 MODW2 &10,%r2 34: fc 41 42 40 SUBW3 %r1,%r2,%r0 38: 04 c9 f0 4c MOVAW -16(%fp),%sp RESTORE %r7 3c: 20 48 POPW %r8 3e: 20 47 POPW %r7 40: 20 49 POPW %fp 42: 08 RET 43: 70 NOP .data WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 68K GAS ucnvrf.s page 1 1 | Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 206F 0004 MOVEAL 4(%SP),%A0 6 0004 48E7 3000 MOVEML %D2/%D3,-(%SP) 7 0008 227C 0000 0000 MOVEAL #WGHTS,%A1 8 000e 4281 CLRL %D1 9 0010 4282 CLRL %D2 10 0012 7609 MOVEQ #9,%D3 11 0014 C0C1 L1: MULUW %D1,%D0 12 0016 D480 ADDL %D0,%D2 13 0018 1018 MOVEB (%A0)+,%D0 14 001a 0400 0030 SUBIB #'0',%D0 15 001e 1219 MOVEB (%A1)+,%D1 16 0020 51CB FFF2 DBF %D3,L1 17 0024 4C41 2003 DIVULL %D1,%D3:%D2 18 0028 4C7C 3001 0000 000A DIVULL #10,%D1:%D3 19 0030 9081 SUBL %D1,%D0 20 0032 4CDF 000C MOVEML (%SP)+,%D2/%D3 21 0036 4E75 RTS 22 0038 0204 0805 0A09 0703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 22 060B x86 NASM ucnvrf.s 1 ; Познайте какво прави тази програма: 2 3 section .text 4 global ucnvrf,_ucnvrf 5 ucnvrf: 6 _ucnvrf: 7 00000000 56 PUSH ESI 8 00000001 96 XCHG EAX,ESI 9 00000002 31D2 XOR EDX,EDX 10 00000004 8D4A0A LEA ECX,[EDX+10] 11 00000007 F6A1[21000000] L1: MUL BYTE [ECX+WGHTS-1] 12 0000000D 6601C2 ADD DX,AX 13 00000010 AC LODSB 14 00000011 2C30 SUB AL,'0' 15 00000013 E2F2 LOOP L1 16 00000015 88C1 L2: MOV CL,AL 17 00000017 92 XCHG EAX,EDX 18 00000018 D40B AAM 11 19 0000001A D40A AAM 20 0000001C B400 MOV AH,0 21 0000001E 28C8 SUB AL,CL 22 00000020 5E POP ESI 23 00000021 C3 RET 24 00000022 060307090A05080402- WGHTS: DB 6,3,7,9,10,5,8,4,2,0 24 0000002B 00 ARM GAS ucnvrf.s page 1 1 // Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 34208FE2 ADD R2,PC,#WGHTS-(.+8) 6 0004 0030A0E3 MOV R3,#0 7 0008 0110D0E4 L1: LDRB R1,[R0],#1 8 000c 301041E2 SUB R1,#'0' 9 0010 01C0D2E4 LDRB R12,[R2],#1 10 0014 0B005CE3 CMP R12,#11 11 0018 913C2310 MLANE R3,R1,R12,R3 12 001c F9FFFF1A BNE L1 13 0020 13FC32E7 UDIV R2,R3,R12 14 0024 920C00E0 MUL R0,R2,R12 15 0028 000043E0 SUB R0,R3,R0 16 002c 0A0050E3 CMP R0,#10 17 0030 0000A003 MOVEQ R0,#0 18 0034 010040E0 SUB R0,R1 19 0038 1EFF2FE1 BX LR 20 003c 02040805 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 20 0A090703 20 060B0000 ARC GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 5928 0200 MPYDU r2,r0,0 6 0004 0A22 800F 0000 0000 MOV r2,WGHTS 7 000c 4A24 8072 MOV lp_count,10 8 0010 A820 8002 LP L1 9 0014 0112 8304 LDB.AB r3,[r2,1] 10 0018 0F2B 4300 MACU r3,r3,r1 11 001c 0110 8104 LDB.AB r1,[r0,1] 12 0020 4221 010C SUB r1,r1,'0' 13 0024 492B C002 L1: REMU r0,r3,11 14 0028 4928 8002 REMU r0,r0,10 15 002c 2278 SUB_S r0,r0,r1 16 002e E07E J_S [blink] 17 .data 18 0000 0002 0408 050A 0907 WGHTS: .byte 0,2,4,8,5,10,9,7,3,6 18 0306 PPC GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 3CA00000 lis r5,(WGHTS-1)@ha 6 0004 38A50000 addi r5,r5,(WGHTS-1)@l 7 0008 38C0000A li r6,10 8 000c 7CC903A6 mtctr r6 9 0010 38C00000 li r6,0 10 0014 3863FFFF addi r3,r3,-1 11 0018 8C830001 L1: lbzu r4,1(r3) 12 001c 3884FFD0 addi r4,r4,-'0 13 0020 8CE50001 lbzu r7,1(r5) 14 0024 42400010 bdz L2 15 0028 7CE439D6 mullw r7,r4,r7 16 002c 7CC63A14 add r6,r6,r7 17 0030 4BFFFFE8 b L1 18 0034 7CA63B96 L2: divwu r5,r6,r7 19 0038 7C6539D6 mullw r3,r5,r7 20 003c 7C633050 subf r3,r3,r6 21 0040 2803000A cmplwi r3,10 22 0044 40820008 bne L3 23 0048 38600000 li r3,0 24 004c 7C641850 L3: subf r3,r4,r3 25 0050 4E800020 blr 26 0054 02040805 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 26 0A090703 26 060B 27 005e 0000 .align 2 SPARC GAS ucnvrf.s page 1 1 ! Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 15000000 set WGHTS,%o2 5 9412A000 6 0008 96100000 clr %o3 7 000c D20A0000 L1: ldub [%o0],%o1 8 0010 90022001 add %o0,1,%o0 9 0014 92226030 sub %o1,'0',%o1 10 0018 19000000 set WGHTS+9,%o4 10 98132000 11 0020 80A2800C cmp %o2,%o4 12 0024 D80A8000 ldub [%o2],%o4 13 0028 1A800005 bcc L2 14 002c 9402A001 add %o2,1,%o2 15 0030 9852400C umul %o1,%o4,%o4 16 0034 10BFFFF6 ba L1 17 0038 9602C00C add %o3,%o4,%o3 18 003c 9472C00C L2: udiv %o3,%o4,%o2 19 0040 9052800C umul %o2,%o4,%o0 20 0044 9022C008 sub %o3,%o0,%o0 21 0048 80A2200A cmp %o0,10 22 004c 12800003 bne L3 23 0050 01000000 nop 24 0054 90100000 clr %o0 25 0058 90220009 L3: sub %o0,%o1,%o0 26 005c 81C3E008 retl 27 0060 01000000 nop 28 .data 29 0000 02040805 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 29 0A090703 29 060B MIPS GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .ent ucnvrf 4 .global ucnvrf 5 ucnvrf: 6 0000 3C060000 24C6006C LA $6,WGHTS 7 0008 3C070000 24E70075 LA $7,WGHTS+9 8 0010 00000013 MTLO $0 9 0014 90850000 L1: LBU $5,0($4) 10 0018 24840001 ADDIU $4,$4,1 11 001c 24A5FFD0 ADDIU $5,$5,-'0' 12 LBU $8,0($6) 13 0020 10C70004 90C80000 BEQ $6,$7,L2 14 0028 24C60001 ADDIU $6,$6,1 15 MADDU $8,$5 16 002c 1000FFF9 71050001 B L1 17 0034 00001012 L2: MFLO $2 18 0038 15000002 0048001B 0007000D DIVU $2,$8 18 00001012 19 0048 00001010 MFHI $2 20 004c 2404000A LI $4,10 21 0050 14800002 0044001B 0007000D DIVU $2,$4 21 00001012 22 0060 00001010 MFHI $2 23 SUBU $2,$2,$5 24 0064 03E00008 00451023 JR $31 25 006c 02040805 0A090703 060B WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 26 0076 00000000 00000000 0000 .end ucnvrf RISC-V GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 17060000 13060600 LA a2,WGHTS 6 0008 97060000 93860600 LA a3,WGHTS+9 7 0010 93070000 MV a5,x0 8 0014 83450500 L1: LBU a1,0(a0) 9 0018 0505 ADDI a0,a0,1 10 001a 938505FD ADDI a1,a1,-'0' 11 001e 03470600 LBU a4,0(a2) 12 0022 6307D600 BEQ a2,a3,L2 13 0026 0506 ADDI a2,a2,1 14 0028 3308B702 MUL a6,a4,a1 15 002c C297 ADD a5,a5,a6 16 002e DDB7 J L1 17 0030 33F5E702 L2: REMU a0,a5,a4 18 0034 2947 LI a4,10 19 0036 3375E502 REMU a0,a0,a4 20 003a 0D8D SUB a0,a0,a1 21 003c 8280 RET 22 003e 02040805 0A090703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 22 060B Nios II GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 34008001 04008031 MOVIA r6,WGHTS 6 0008 3400C001 0400C039 MOVIA r7,WGHTS+9 7 0010 3A881300 MOV r9,r0 8 0014 03004021 L1: LDBU r5,(r4) 9 0018 44000021 ADDI r4,r4,1 10 001c 04F47F29 SUBI r5,r5,'0' 11 0020 03000032 LDBU r8,(r6) 12 0024 2604C031 BEQ r6,r7,L2 13 0028 44008031 ADDI r6,r6,1 14 002c 3A385541 MUL r10,r8,r5 15 0030 3A88934A ADD r9,r9,r10 16 0034 06F73F00 BR L1 17 0038 3A20094A L2: DIVU r4,r9,r8 18 003c 3A381141 MUL r8,r8,r4 19 0040 3AC8114A SUB r8,r9,r8 20 0044 98020041 CMPNEI r4,r8,10 21 0048 3A380922 MUL r4,r4,r8 22 004c 3AC84521 SUB r2,r4,r5 23 0050 3A2800F8 RET 24 0054 02040805 0A090703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 24 060B0000 Xtensa GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 410000 MOVI a4,WGHTS 6 0003 510000 MOVI a5,WGHTS+9 7 0006 0C07 MOVI a7,0 8 0008 320200 L1: L8UI a3,a2,0 9 000b 1B22 ADDI a2,a2,1 10 000d 32C3D0 ADDI a3,a3,-'0' 11 0010 620400 L8UI a6,a4,0 12 0013 571409 BEQ a4,a5,L2 13 0016 1B44 ADDI a4,a4,1 14 0018 308682 MULL a8,a6,a3 15 001b 8A77 ADD a7,a7,a8 16 001d C6F9FF J L1 17 0020 6027E2 L2: REMU a2,a7,a6 18 0023 0CA6 MOVI a6,10 19 0025 6022E2 REMU a2,a2,a6 20 0028 3022C0 SUB a2,a2,a3 21 002b 0DF0 RET 22 002d 02040805 0A090703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 22 060B 88K GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global _ucnvrf 4 0000 5C600000 _ucnvrf: 5 0004 58830058 or.u r3,r0,hi16(WGHTS) 6 0008 58E0000A or r4,r3,lo16(WGHTS) 7 000c F4A05800 or r7,r0,10 8 0010 0C620000 or r5,r0,r0 9 0014 60420001 L1: ld.bu r3,r2,0 10 0018 64630030 addu r2,r2,1 11 001c 0CC40000 subu r3,r3,'0' 12 0020 60840001 ld.bu r6,r4,0 13 0024 64E70001 addu r4,r4,1 14 0028 E8470004 subu r7,r7,1 15 002c F4C36C06 bcnd eq0,r7,L2 16 0030 F4A56006 mul r6,r3,r6 17 0034 C3FFFFF7 addu r5,r5,r6 18 0038 F4856806 br L1 19 003c F4446C06 L2: divu r4,r5,r6 20 0040 F4456402 mul r2,r4,r6 21 0044 7CE2000A subu r2,r5,r2 22 0048 D8670002 cmp r7,r2,10 23 004c F4405800 bb1 ne,r7,L3 24 0050 F4426403 or r2,r0,r0 25 0054 F400C001 L3: subu r2,r2,r3 26 0058 02040805 jmp r1 26 0A090703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 26 060B Or1k GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 18A00000 L.MOVHI R5,HI(WGHTS) 6 0004 A8A50000 L.ORI R5,R5,LO(WGHTS) 7 0008 9CC50009 L.ADDI R6,R5,9 8 000c 18810000 L.MACRC R4 9 0010 8C830000 L1: L.LBZ R4,0(R3) 10 0014 9C630001 L.ADDI R3,R3,1 11 0018 9C84FFD0 L.ADDI R4,R4,-'0' 12 001c 8CE50000 L.LBZ R7,0(R5) 13 0020 E4053000 L.SFEQ R5,R6 14 0024 10000004 L.BF L2 15 0028 9CA50001 L.ADDI R5,R5,1 16 002c 03FFFFF9 L.J L1 17 0030 C4043803 L.MACU R4,R7 18 0034 18C10000 L2: L.MACRC R6 19 0038 E0A63B0A L.DIVU R5,R6,R7 20 003c E0653B0B L.MULU R3,R5,R7 21 0040 E0661802 L.SUB R3,R6,R3 22 0044 BC03000A L.SFEQI R3,10 23 0048 E160180E L.CMOV R11,R0,R3 24 004c 44004800 L.JR LR 25 0050 E16B2002 L.SUB R11,R11,R4 26 0054 02040805 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 26 0A090703 26 060B Xilinx MicroBlaze GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 000000B0 5C00E0A0 ORI R7,R0,WGHTS 6 0008 000000B0 650000A1 ORI R8,R0,WGHTS+9 7 0010 00006080 OR R3,R0,R0 8 0014 0000C5E0 L1: LBUI R6,R5,0 9 0018 0100A520 ADDI R5,R5,1 10 001c D0FFC620 ADDI R6,R6,-'0' 11 0020 000027E1 LBUI R9,R7,0 12 0024 0044878C PCMPNE R4,R7,R8 13 0028 140004BC BEQI R4,L2 14 002c 0100E720 ADDI R7,R7,1 15 0030 00308940 MUL R4,R9,R6 16 0034 00206300 ADD R3,R3,R4 17 0038 DCFF00B8 BRI L1 18 003c 02188948 L2: IDIVU R4,R9,R3 19 0040 0020A940 MUL R5,R9,R4 20 0044 00186504 RSUB R3,R5,R3 21 0048 F6FF8320 ADDI R4,R3,-10 22 004c 0004848C PCMPNE R4,R4,R0 23 0050 00206340 MUL R3,R3,R4 24 0054 08000FB6 RTSD R15,8 25 0058 00186604 RSUB R3,R6,R3 26 005c 02040805 0A090703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 26 060B HPPA GAS ucnvrf.s page 1 1 ; Познайте какво прави тази подпрограма: 2 3 .text 4 .import UDIV,code 5 .global ucnvrf 6 ucnvrf: 7 0000 0802025F COPY %R2,%R31 8 0004 23200000 LDIL L%WGHTS,%R25 9 0008 37390000 LDO R%WGHTS(%R25),%R25 10 000c 34180000 LDI 0,%R24 11 0010 34170014 LDI 10,%R23 12 0014 0F421036 L1: LDBS,MA 1(%R26),%R22 13 0018 B6D607A1 ADDI -'0,%R22,%R22 14 001c A6FF2010 ADDIBT,= -1,%R23,L2 15 0020 0F360015 LDBX %R22(%R25),%R21 16 0024 AB151FD5 ADDBF %R21,%R24,L1 17 0028 B7390014 ADDI 10,%R25,%R25 18 002c E8400000 L2: BL UDIV,%R2 19 0030 341A0016 LDI 11,%R26 20 0034 93A07014 COMICLR,> 10,%R29,%R0 21 0038 341D0000 LDI 0,%R29 22 003c 0BB6041C SUB %R22,%R29,%R28 23 0040 EBE0C002 BV,N (%R31) 24 0044 00020406 WGHTS: .byte 0, 2, 4, 6, 8,10,12,14,16,18, 0, 4, 8,12,16,20,24,28,32,36 24 080A0C0E 24 10120004 24 080C1014 24 181C2024 25 0058 00081018 .byte 0, 8,16,24,32,40,48,56,64,72, 0, 5,10,15,20,25,30,35,40,45 25 20283038 25 40480005 25 0A0F1419 25 1E23282D 26 006c 000A141E .byte 0,10,20,30,40,50,60,70,80,90, 0, 9,18,27,36,45,54,63,72,81 26 28323C46 26 505A0009 26 121B242D 26 363F4851 27 0080 00070E15 .byte 0, 7,14,21,28,35,42,49,56,63, 0, 3, 6, 9,12,15,18,21,24,27 27 1C232A31 27 383F0003 27 06090C0F 27 1215181B 28 0094 00060C12 .byte 0, 6,12,18,24,30,36,42,48,54 28 181E242A 28 30360000 UNDEFINED SYMBOLS UDIV Renesas / SuperH SH GAS Little Endian ucnvrf.s page 1 1 ! Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 10D6 MOV.L WGHTPTR,R6 6 0002 00E7 MOV #0,R7 7 0004 2800 CLRMAC 8 0006 4465 L1: MOV.B @R4+,R5 9 0008 D075 ADD #-'0',R5 10 000a 0FD0 MOV.L WGHTEND,R0 11 000c 0236 CMP/HS R0,R6 12 000e 6460 MOV.B @R6+,R0 13 0010 0389 BT L2 14 0012 5E20 MULU.W R5,R0 15 0014 1A00 STS MACL,R0 16 0016 F6AF BRA L1 17 0018 0C37 ADD R0,R7 18 001a 0364 L2: MOV R0,R4 19 001c 0BD0 MOV.L UDIVPTR,R0 20 001e 2A06 STS PR,R6 21 0020 0B40 JSR @R0 22 0022 1A47 LDS R7,MACL 23 0024 2A46 LDS R6,PR 24 0026 0E24 MULU.W R0,R4 25 0028 1A00 STS MACL,R0 26 002a 0837 SUB R0,R7 27 002c 7360 MOV R7,R0 28 002e 0A88 CMP/EQ #10,R0 29 0030 008B BF L3 30 0032 00E0 MOV #0,R0 31 0034 0B00 L3: RTS 32 0036 5830 SUB R5,R0 33 0038 02040805 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 33 0A090703 33 060B 34 0042 0900 .align 2 35 0044 38000000 WGHTPTR:.long WGHTS 36 0048 41000000 WGHTEND:.long WGHTS+9 37 004c 00000000 UDIVPTR:.long UDIV UNDEFINED SYMBOLS UDIV GAS for CRIS ucnvrf.s page 1 1 ; Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 0000 6FCE0000 0000 MOVE.D WGHTS,$R12 6 0006 7D86 CLEAR.D $R13 7 0008 4AFE L1: MOVE.B [$R10+],$R15 8 000a B0F2 SUBQ '0',$R15 9 000c EFCE0000 0000 CMP.D WGHTS+9,$R12 10 0012 0A00 BHS L2 11 0014 4CBE MOVE.B [$R12+],$R11 12 0016 0FB9 MULU.B $R15,$R11 13 0018 F1E0 BA L1 14 001a 2BD6 ADD.D $R11,$R13 15 001c BF7E0000 0000 L2: BAS UDIV16,$MOF 16 0022 6DA6 MOVE.D $R13,$R10 17 0024 CAB2 CMPQ 10,$R11 18 0026 0620 BNE L3 19 0028 6BA6 MOVE.D $R11,$R10 20 002a 7A86 CLEAR.D $R10 21 002c F0B9 L3: RET 22 002e 8FA6 SUB.B $R15,$R10 23 0030 02040805 0A090703 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 23 060B0000 UNDEFINED SYMBOLS UDIV16 BFIN GAS ucnvrf.s page 1 1 # Познайте какво прави тази подпрограма: 2 3 .global _ucnvrf 4 _ucnvrf: 5 0000 0032 P0 = R0; 6 0002 49E10000 P1.H = WGHTS; 7 0006 09E10000 P1.L = WGHTS; 8 000a 0060 R0 = 0; 9 000c 0160 R1 = 0; 10 000e 08C40000 A0 = 0; 11 0012 5268 P2 = 10; 12 0014 A2E00620 LSETUP (L_1, L_2) LC0 = P2; 13 0018 03C10108 L_1: A0 += R0.L * R1.L (IS); 14 001c 0098 R0 = B [P0++] (Z); 15 001e 8066 R0 += -'0'; 16 0020 0998 L_2: R1 = B [P1++] (Z); 17 0022 1030 R2 = R0; 18 0024 0BC00038 R0 = A0; 19 0028 0F33 P1 = RETS; 20 002a FFE3EBFF CALL _UDIV16; 21 002e 7938 RETS = P1; 22 0030 03C10110 A0 -= R0.L * R1.L (IS); 23 0034 0BC00038 R0 = A0; 24 0038 5160 R1 = 10; 25 003a 8808 CC = R0 < R1; 26 003c 021C IF CC JUMP L_3 (BP); 27 003e 0060 R0 = 0; 28 0040 1052 L_3: R0 = R0 - R2; 29 0042 1000 RTS; 30 .data 31 0000 02040805 WGHTS: .byte 2,4,8,5,10,9,7,3,6,11 31 0A090703 31 060B0000 UNDEFINED SYMBOLS _UDIV16 Hexagon GAS ucnvrf.s page 1 1 // Познайте какво прави тази подпрограма: 2 3 .global ucnvrf 4 ucnvrf: 5 { R1 = #WGHTS 6 R3:2 = #0 7 0000 5A400069 00400000 013C0128 LOOP0 (L1,#10) } 8 000C 24C0219B L1: R4 = MEMUB(R1++#1) 9 { R2 += MPYI(R3,R4) 10 0010 024403EF 23C0209B R3 = MEMUB(R0++#1) } 11 0018 03BAE3BF 00C0007F { R3 = ADD(R3,#-'0') }:ENDLOOP0 12 0020 45577401 A1C60078 R1 = #0x1745D175 13 0028 21C241ED R1 = MPYU(R1,R2) 14 002C 61C101E0 R1 = MPYI(R1,#11) 15 { R1 = SUB(R2,R1) 16 0030 014221F3 44C10078 R4 = #10 } 17 0038 E1C4E1D3 R1 = MODWRAP(R1,R4) 18 { R0 = SUB(R1,R3) 19 003C 004123F3 00C09F52 JUMPR LR } 20 .data 21 0000 00020408 050A0907 0306 WGHTS: .byte 0,2,4,8,5,10,9,7,3,6 S/390 GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър 2 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 A7580006 LHI 5,6 # Изваждащ брояч 8 0004 A7380001 LHI 3,1 # Предидущо число 9 0008 1843 LR 4,3 # Текущо число 10 000a B2520034 L1: MSR 3,4 # S[i] = S[i-1] * (S[i-1] - 1) 11 000e 41403001 LA 4,1(3) # S[i] = S[i-1] * (S[i-1] - 1) + 1 12 0012 50402000 ST 4,0(2) # Запиши S[i] в масива 13 0016 A72A0004 AHI 2,4 # Обнови адреса 14 001a A756FFF8 BRCT 5,L1 # Премини към следващото число 15 001e 07FE BR 14 # Върни се към извикващата програма ==> id32/sequence.s <== 1 * Write in an array of words starting at 7(4) -> register 3 the first 6 2 * numbers of the Sylvester's sequence, the first of which is 2, and 3 * each of the next is equal to the product of the all before it plus 1. 4 5 entry sequence 00000000d 6 sequence equ * 00000d 5837 0000 7 l 3,0(7) Buffer address 00004d 2411 8 lis 1,1 Previous number 00006d 0801 9 lr 0,1 Current number 00008d 2426 10 lis 2,6 Initialise the decreasing counter 0000Ad 1C00 11 L1 mr 0,0 S[i] = S[i-1] * (S[i-1] - 1) 0000Cd 0801 12 lr 0,1 "la" adds only a 20-bit address, so it's unusable here! 0000Ed 2601 13 ais 0,1 S[i] = S[i-1] * (S[i-1] - 1) + 1 00010d 5003 0000 14 st 0,0(3) Write S[i] into the array 00014d 2634 15 ais 3,4 Update the address 00016d 2721 16 sis 2,1 Last number? 00018d 2037 0000000Ad 17 bnzs L1 No, go to the next number 0001Ad 030F 18 br 15 Yes, return to the calling function VAX GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в AP(4) -> R0 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global _sequence 6 _sequence: 7 0000 0C00 .word 0xC # R2-R3 8 0002 D0AC0450 MOVL 4(AP),R0# Начален адрес 9 0006 D00151 MOVL $1,R1 # Текущо число 10 0009 C1015152 L1: ADDL3 $1,R1,R2# S[i] = S[i-1] * (S[i-1] - 1) + 1 11 000d D05280 MOVL R2,(R0)+# Запиши S[i] в масива 12 0010 C45251 MULL2 R2,R1 # S[i] = S[i-1] * (S[i-1] - 1) 13 0013 1CF4 BVC L1 # Ако има препълване, край на цикъла 14 0015 040101 RET # Върни се към извикващата програма ==> we32k/sequence.s <== # Write in an array of words starting at ap(4) -> r3 the first 6 numbers of # the Sylvester's sequence, the first of which is 2, and each of the next is # equal to the product of the all before it plus 1. section .text .globl sequence sequence() sequence: 0: a0 43 PUSHW %r3 # "AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 43 MOVW 0(%ap),%r3 # Programming Manual", pp. 6-13, 6-14 5: 84 01 40 MOVW &1,%r0 # Previous number 8: 84 40 41 MOVW %r0,%r1 # Current number b: 84 06 42 MOVW &6,%r2 # Initialise the decreasing counter e: a8 41 40 L1: MULW2 %r1,%r0 # S[i] = S[i-1] * (S[i-1] - 1) 11: dc 01 40 41 ADDW3 &1,%r0,%r1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 15: 84 41 53 MOVW %r1,(%r3) # Write S[i] into the array 18: 70 NOP 19: 9c 04 43 ADDW2 &4,%r3 # Update the address 1c: 94 42 DECW %r2 # Last number? 1e: 77 f0 BNEB L1 # No, go to the next number 20: 20 43 POPW %r3 # Yes, restore the saved register 22: 08 RET # Return to the calling function 23: 70 NOP 68K GAS sequence.s page 1 1 | Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 | в SP(4) -> D0 първите 6 числа от редицата на Силвестър, първото от които е 3 | 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 206F 0004 MOVEL 4(%SP),%A0 | Начален адрес 8 0004 7001 MOVEQ #1,%D0 | Текущо число 9 0006 2200 L1: MOVEL %D0,%D1 | Предидущо число 10 0008 5281 ADDQL #1,%D1 | S[i] = S[i-1] * (S[i-1] - 1) + 1 11 000a 20C1 MOVEL %D1,(%A0)+ | Запиши S[i] в масива 12 000c 4C01 0000 MULUL %D1,%D0 | S[i] = S[i-1] * (S[i-1] - 1) 13 0010 6800 FFF4 BVC L1 | Ако няма препълване, продължи цикъла 14 0014 4E75 RTS | Върни се към извикващата програма x86 NASM sequence.s 1 ; Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 ; в регистър EAX първите 6 числа от редицата на Силвестър, първото от които е 3 ; 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 section .text 6 global sequence,_sequence; в GCC декларирай с __attribute__((regparm(3))) 7 sequence: 8 _sequence: 9 00000000 60 PUSHAD ; GCC изисква EBX и EDI да се съхраняват 10 00000001 97 XCHG EDI,EAX 11 00000002 B801000000 MOV EAX,1 ; Текущо число (MUL променя EDX -> неизползваем е) 12 00000007 89C3 L1: MOV EBX,EAX ; Съхрани S[i-1] - 1 за евентуална следваща итерация 13 00000009 40 INC EAX ; S[i] = S[i-1] * (S[i-1] - 1) + 1 14 0000000A AB STOSD ; Запиши S[i] в масива 15 0000000B F7E3 MUL EBX ; S[i] = S[i-1] * (S[i-1] - 1) 16 0000000D 73F8 JNC L1 ; Ако старшата дума на произведението в DX != 0, край 17 0000000F 61 POPAD ; Възстанови съхранените регистри 18 00000010 C3 RET ; Върни се към извикващата програма ARM GAS sequence.s page 1 1 // Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 // в регистър R0 първите 6 числа от редицата на Силвестър, първото от които е 3 // 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 0110A0E3 MOV R1,#1 // Текущо число 8 0004 012081E2 L1: ADD R2,R1,#1 // S[i] = S[i-1] * (S[i-1] - 1) + 1 9 0008 042080E4 STR R2,[R0],#4 // запиши S[i] в масива 10 000c 921183E0 UMULL R1,R3,R2,R1 // S[i] = S[i-1] * (S[i-1] - 1) 11 0010 000053E3 CMP R3,#0 // Събира ли се произведението в 32 бита? 12 0014 FAFFFF0A BEQ L1 // Да, премини към следващото число 13 0018 1EFF2FE1 BX LR // Не, върни се към извикващата програма ARC GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър r0 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 2C71 MOV_S r1,1 # Текущо число 8 0002 4169 L1: ADD_S r2,r1,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 9 0004 0418 9000 ST.AB r2,[r0,4] # запиши S[i] в масива и обнови адреса 10 0008 1D22 4180 MPYU.F r1,r2,r1 # S[i] = S[i-1] * (S[i-1] - 1) 11 000c F607 C8FF BVC L1 # Ако произведението се побира в 32 бита, 12 0010 E07E J_S [blink] # продължи, иначе върни управлението PPC GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър r3 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 3863FFFC addi r3,r3,-4# Компенсирай автоматичното предварително увеличение 8 0004 38800006 li r4,6 # Изваждащ брояч 9 0008 7C8903A6 mtctr r4 10 000c 38800001 li r4,1 # Предидущо число 11 0010 38A00001 li r5,1 # Текущо число 12 0014 7C8429D6 L1: mullw r4,r4,r5# S[i] = S[i-1] * (S[i-1] - 1) 13 0018 38A40001 addi r5,r4,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 14 001c 94A30004 stwu r5,4(r3)# Запиши S[i] в масива 15 0020 4200FFF4 bdnz L1 # Премини към следващото число 16 0024 4E800020 blr # Върни се към извикващата програма SPARC GAS sequence.s page 1 1 ! Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 ! в регистър %o0 първите 6 числа от редицата на Силвестър, първото от които е 3 ! 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 92102001 mov 1,%o1 ! Предидущо число 8 0004 94102001 mov 1,%o2 ! Текущо число 9 0008 96102006 mov 6,%o3 ! Изваждащ брояч 10 000c 9252400A L1: umul %o1,%o2,%o1! S[i] = S[i-1] * (S[i-1] - 1) 11 0010 94026001 add %o1,1,%o2 ! S[i] = S[i-1] * (S[i-1] - 1) + 1 12 0014 D4220000 st %o2,[%o0] ! Запиши S[i] в масива 13 0018 90022004 add %o0,4,%o0 ! Обнови адреса 14 001c 96A2E001 subcc %o3,1,%o3 ! Намали съдържанието на брояча; i == 6? 15 0020 12BFFFFB bne L1 ! Не, премини към следващото число 16 0024 01000000 nop ! Да, върни се към извикващата програма 17 0028 81C3E008 retl 18 002c 01000000 nop MIPS GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър $4 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .ent sequence 6 .global sequence 7 sequence: 8 0000 24070006 LI $7,6 # Изваждащ брояч 9 0004 24050001 LI $5,1 # Предидущо число 10 0008 24060001 LI $6,1 # Текущо число 11 000c 70A62802 L1: MUL $5,$5,$6# S[i] = S[i-1] * (S[i-1] - 1) 12 0010 24A60001 ADDIU $6,$5,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 13 0014 AC860000 SW $6,0($4)# Запиши S[i] в масива 14 0018 24840004 ADDIU $4,$4,4 # Укажи към следващия елемент на масива 15 001c 24E7FFFF ADDIU $7,$7,-1# Има ли още числа? 16 0020 14E0FFFA 00000000 BNE $7,$0,L1# Да, премини към следващото 17 0028 03E00008 00000000 JR $31 # Не, върни се към извикващата програма 18 .end sequence RISC-V GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър a0 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 9946 LI a3,6 # Изваждащ брояч 8 0002 8545 LI a1,1 # Предидущо число 9 0004 0546 LI a2,1 # Текущо число 10 0006 B385C502 L1: MUL a1,a1,a2 # S[i] = S[i-1] * (S[i-1] - 1) 11 000a 13861500 ADDI a2,a1,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 12 000e 10C1 SW a2,0(a0) # Запиши S[i] в масива 13 0010 1105 ADDI a0,a0,4 # Укажи към следващия елемент на масива 14 0012 FD16 ADDI a3,a3,-1 # Има ли още числа? 15 0014 EDFA BNEZ a3,L1 # Да, премини към следващото 16 0016 8280 RET # Не, върни се към извикващата програма Nios II GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър r4 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 9401C001 MOVUI r7,6 # Изваждащ брояч 8 0004 54004001 MOVUI r5,1 # Предидущо число 9 0008 54008001 MOVUI r6,1 # Текущо число 10 000c 3A388B29 L1: MUL r5,r5,r6# S[i] = S[i-1] * (S[i-1] - 1) 11 0010 44008029 ADDI r6,r5,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 12 0014 15008021 STW r6,(r4) # Запиши S[i] в масива 13 0018 04010021 ADDI r4,r4,4 # Укажи към следващия елемент на масива 14 001c C4FFFF39 SUBI r7,r7,1 # Има ли още числа? 15 0020 1EFA3F38 BNE r7,r0,L1# Да, премини към следващото 16 0024 3A2800F8 RET # Не, върни се към извикващата програма Xtensa GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър a2 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 0C13 MOVI a3,1 # Предидущо число 8 0002 0C14 MOVI a4,1 # Текущо число 9 0004 0C65 MOVI a5,6 # Задай брой итерации, 10 0006 768508 LOOP a5,L1 # начален и краен адреса на цикъла 11 0009 403382 MULL a3,a3,a4 # S[i] = S[i-1] * (S[i-1] - 1) 12 000c 1B43 ADDI a4,a3,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 13 000e 4902 S32I a4,a2,0 # Запиши S[i] в масива 14 0010 4B22 ADDI a2,a2,4 # Укажи към следващия елемент на масива 15 0012 0DF0 L1: RET # Върни се към извикващата програма 88K GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър r2 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global _sequence 6 0000 58A00006 _sequence: 7 0004 58600001 or r5,r0,6 # Изваждащ брояч 8 0008 58800001 or r3,r0,1 # Предидущо число 9 000c F4636C04 or r4,r0,1 # Текущо число 10 0010 60830001 L1: mul r3,r3,r4 # S[i] = S[i-1] * (S[i-1] - 1) 11 0014 24820000 addu r4,r3,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 12 0018 60420004 st r4,r2,0 # Запиши S[i] в масива 13 001c 64A50001 addu r2,r2,4 # Обнови адреса 14 0020 E9A5FFFB subu r5,r5,1 # Намали съдържанието на брояча; i == 6? 15 0024 F400C001 bcnd ne0,r5,L1# Не, премини към следващото jmp r1 # Да, върни се към извикващата програма Or1k GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър R3 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 A8C00006 L.ORI R6,R0,6 # Изваждащ брояч 8 0004 A8800001 L.ORI R4,R0,1 # Предидущо число 9 0008 A8A00001 L.ORI R5,R0,1 # Текущо число 10 000c E0842B06 L1: L.MUL R4,R4,R5# S[i] = S[i-1] * (S[i-1] - 1) 11 0010 9CA40001 L.ADDI R5,R4,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 12 0014 D4032800 L.SW 0(R3),R5# Запиши S[i] в масива 13 0018 9CC6FFFF L.ADDI R6,R6,-1# Обнови брояча 14 001c E4260000 L.SFNE R6,R0 # Има ли още числа? 15 0020 13FFFFFB L.BF L1 # Да, премини към следващото 16 0024 9C630004 L.ADDI R3,R3,4 # (укажи към следващия елемент; изп.се преди „L.BF“!) 17 0028 44004800 L.JR LR # Не, върни се към извикващата програма 18 002c 15000000 L.NOP 0 Xilinx MicroBlaze GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър R5 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 0100C0A0 ORI R6,R0,1 # Предидущо число 8 0004 0100E0A0 ORI R7,R0,1 # Текущо число 9 0008 060000A1 ORI R8,R0,6 # Изваждащ брояч 10 000c 0030C740 L1: MUL R6,R7,R6# S[i] = S[i-1] * (S[i-1] - 1) 11 0010 0100E620 ADDI R7,R6,1 # S[i] = S[i-1] * (S[i-1] - 1) + 1 12 0014 0000E5F8 SWI R7,R5,0 # Запиши S[i] в масива 13 0018 0400A520 ADDI R5,R5,4 # Обнови адреса 14 001c FFFF0821 ADDI R8,R8,-1# Намали съдържанието на брояча; i == 6? 15 0020 ECFF28BC BNEI R8,L1 # Не, премини към следващото число 16 0024 08000FB6 RTSD R15,8 # Да, върни се към извикващата програма 17 0028 00000080 NOP HPPA GAS sequence.s page 1 1 ; Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 ; в регистър %R26 първите 6 числа от редицата на Силвестър, първото от които 3 ; е 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .text 6 .global sequence 7 sequence: 8 0000 34190002 LDI 1,%R25 ; Предидущо число 9 0004 08190258 COPY %R25,%R24 ; Текущо число 10 0008 3417000C LDI 6,%R23 ; Изваждащ брояч 11 000c 0FD91281 L1: STW %R25,-16(%SP) 12 0010 0FD81289 STW %R24,-12(%SP) 13 0014 2FC11016 FLDDS -16(%SP),%FR22 14 0018 3AD65716 XMPYU %FR22L,%FR22R,%FR22 15 001c 2FC11216 FSTDS %FR22,-16(%SP) 16 0020 0FC91099 LDW -12(%SP),%R25 ; S[i] = S[i-1] * (S[i-1] - 1) 17 0024 B7380002 ADDI 1,%R25,%R24 ; S[i] = S[i-1] * (S[i-1] - 1) + 1 18 0028 AEFF3FBD ADDIBF,= -1,%R23,L1 ; Премини към следващото число 19 002c 6F580008 STWM %R24,4(%R26) ; Запиши S[i] в масива (изп. се преди „ADDIBF“) 20 0030 E840C002 BV,N (%R2) ; Върни се към извикващата програма 20 00000000 Renesas / SuperH SH GAS Little Endian sequence.s page 1 1 ! Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 ! в регистър R4 първите 6 числа от редицата на Силвестър, първото от които е 3 ! 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 01E1 MOV #1,R1 ! Предидущо число 8 0002 1362 MOV R1,R2 ! Текущо число 9 0004 06E3 MOV #6,R3 ! Изваждащ брояч 10 0006 2701 L1: MUL.L R2,R1 ! S[i] = S[i-1] * (S[i-1] - 1) 11 0008 1A01 STS MACL,R1 12 000a 1362 MOV R1,R2 13 000c 0172 ADD #1,R2 ! S[i] = S[i-1] * (S[i-1] - 1) + 1 14 000e 2224 MOV.L R2,@R4 ! Запиши S[i] в масива 15 0010 0474 ADD #4,R4 ! Обнови адреса 16 0012 1043 DT R3 ! Последно число? 17 0014 F78B BF L1 ! Не, продължи 18 0016 0B00 RTS ! Да, върни се към извикващата програма 19 0018 0900 NOP GAS for CRIS sequence.s page 1 1 ; Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 ; в регистър R10 първите 6 числа от редицата на Силвестър, първото от които е 3 ; 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 0000 46D2 MOVEQ 6,$R13 ; Изваждащ брояч 8 0002 41B2 MOVEQ 1,$R11 ; Предидущо число 9 0004 41F2 MOVEQ 1,$ACR ; Текущо число 10 0006 2FB9 L1: MULU.D $ACR,$R11 ; S[i] = S[i-1] * (S[i-1] - 1) 11 0008 01B1 ADDOQ 1,$R11,$ACR ; S[i] = S[i-1] * (S[i-1] - 1) + 1 12 000a 81D2 SUBQ 1,$R13 13 000c FB20 BNE L1 ; Премини към следващото число (след „MOVE“!) 14 000e EAFF MOVE.D $ACR,[$R10+] ; Запиши S[i] в масива и обнови адреса 15 0010 F0B9 RET ; Върни се към извикващата програма 16 0012 B005 NOP BFIN GAS sequence.s page 1 1 # Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 # в регистър R0 първите 6 числа от редицата на Силвестър, първото от които е 3 # 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global _sequence 6 _sequence: 7 0000 0032 P0 = R0; # Адрес на буфера 8 0002 0960 R1 = 1; # Предидущо число 9 0004 1130 R2 = R1; # Текущо число 10 0006 0130 R0 = R1; # Добавка за S[i] 11 0008 3168 P1 = 6; # Задай брой итерации, 12 000a A2E00410 LSETUP (L_1, L_2) LC0 = P1;# начален и краен адреса на цикъла 13 000e D140 L_1: R1 *= R2; # S[i] = S[i-1] * (S[i-1] - 1) 14 0010 8150 R2 = R1 + R0; # S[i] = S[i-1] * (S[i-1] - 1) + 1 15 0012 0292 L_2: [P0++] = R2; # Запиши S[i] в масива 16 0014 10000000 RTS; # Върни се към извикващата програма Hexagon GAS sequence.s page 1 1 // Да се напише подпрограма, която да записва в масив от думи с начален адрес 2 // в регистър R0 първите 6 числа от редицата на Силвестър, първото от които е 3 // 2, а всяко следващо е равно на произведението на всички предидущи плюс 1. 4 5 .global sequence 6 sequence: 7 { R1 = #1 // Текущо число 8 0000 32400069 21C00078 LOOP0 (L1,#6) } // Начало и брой итерации на цикъла 9 0008 22C001B0 L1: R2 = ADD(R1,#1) // S[i] = S[i-1] * (S[i-1] - 1) + 1 10 { MEMW(R0++#4) = R2 // Запиши S[i] в масива 11 000c 018102ED 08C280AB R1 = MPYI(R2,R1) }:ENDLOOP0 // S[i] = S[i-1] * (S[i-1] - 1) 12 0014 00C09F52 JUMPR LR // Върни се към извикващата програма S/390 GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър 2 индекса на подадената 2 # в регистри 2:3 двойна дума в масива от двойни думи (BE) с начален адрес в 3 # реигистър 5 и брой елементи в регистър 4, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 5060F008 ST 6,8(15) # Съхрани използвания регистър (LNUX-1007-02) 8 0004 A768FFFF LHI 6,-1 # Инициализирай индекса 9 0008 A76A0001 L1: AHI 6,1 # Актуализирай го 10 000c 98015000 LM 0,1,0(5)# Зареди следващата двойна дума 11 0010 A75A0008 AHI 5,8 # Обнови адреса 12 0014 1531 CLR 3,1 # Съвпадат ли младшите думи? 13 0016 A7740005 JNE L2 # Не 14 001a 1520 CLR 2,0 # Да, съвпадат ли и старшите? 15 001c A7840006 JE L3 # Да, излез от цикъла 16 0020 A746FFF4 L2: BRCT 4,L1 # Не, продължи със следващия елемент 17 0024 A768FFFF LHI 6,-1 # Двойната дума в регистри 2:3 не е намерена, върни -1 18 0028 1826 L3: LR 2,6 # Върни индекса на откритата съвпадаща двойна дума 19 002a 5860F008 L 6,8(15) # Възстанови съхранения регистър 20 002e 07FE BR 14 # Върни управлението ==> id32/search64.s <== 1 * Return in register 0 the index of the double word passed in 7(0) in the 2 * array of double words (BE) starting at 7(12) and having 7(8) element, or 3 * -1 if not found. 4 5 entry search64 00000000d 6 search64 equ * 00000d 5817 0000 7 l 1,0(7) High word of the double word to be searched for 00004d 5827 0004 8 l 2,4(7) Low " " " " " " " " " " " 00008d 5837 0008 9 l 3,8(7) Member count 0000Cd 5847 000C 10 l 4,12(7) Starting address 00010d 2501 11 lcs 0,1 Initialise the index with -1 00012d 2601 12 L1 ais 0,1 Update it 00014d 5914 0000 13 c 1,0(4) Do the high words coincide? 00018d 2134 00000020d 14 bnzs L2 No 0001Ad 5924 0004 15 c 2,4(4) Yes, do the low ones coincide too? 0001Ed 2335 00000028d 16 bzs L3 Yes, exit the loop 00020d 2648 17 L2 ais 4,8 Update the address 00022d 2731 18 sis 3,1 Any more members? 00024d 2039 00000012d 19 bnzs L1 Yes, continue with the next one 00026d 2501 20 lcs 0,1 No, double word in registers 1:2 not found, return -1 00028d 030F 21 L3 br 15 Return to the calling function VAX GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 # в AP(8):AP(4) двойна дума в масива от двойни думи (LE) с начален адрес в 3 # AP(16) и брой елементи в AP(12), или -1, ако не е намерена. 4 5 .global _search64 6 _search64: 7 0000 7C00 .word 0x7C # R2-R6 8 0002 FD7DAC04 50 MOVO 4(AP),R0# R1:R0 = двойна дума, R2 = брой елементи, R3 = адрес 9 0007 D08FFFFF FFFF54 MOVL $-1,R4 # Инициализирай индекса 10 000e D654 L1: INCL R4 # Актуализирай го 11 0010 7D8355 MOVQ (R3)+,R5# Зареди следващата двойна дума 12 0013 D15055 CMPL R0,R5 # Съвпадат ли младшите думи? 13 0016 1205 BNEQ L2 # Не 14 0018 D15156 CMPL R1,R6 # Да, съвпадат ли и старшите? 15 001b 130A BEQL L3 # Да, излез от цикъла 16 001d F552EE L2: SOBGTR R2,L1 # Не, продължи със следващия елемент 17 0020 D08FFFFF FFFF54 MOVL $-1,R4 # Двойната дума в R1:R0 не е намерена, върни -1 18 0027 D05450 L3: MOVL R4,R0 # Върни индекса на откритата съвпадаща двойна дума 19 002a 0401 RET # Върни управлението ==> we32k/search64.s <== # Return in r0 the index of the double word passed in ap(0):ap(4) in the array # of double words (BE) starting at ap(12) and having ap(8) elements, or -1 if # not found. section .text .globl search64 search64() search64: 0: 10 47 SAVE %r7 #"AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 41 MOVW 0(%ap),%r1 # Programming Manual", pp. 6-13, 6-14 5: 84 74 42 MOVW 4(%ap),%r2 # r1:r2 = the double word to be searched for 8: 84 78 47 MOVW 8(%ap),%r7 # member count b: 84 7c 48 MOVW 12(%ap),%r8 # starting address e: 84 ff 40 MOVW &-1,%r0 # Initialise the index 11: 90 40 L1: INCW %r0 # Update it 13: 3c 41 58 CMPW %r1,(%r8) # Do the high words coincide? 16: 77 08 BNEB L2 # No 18: 3c 42 c8 04 CMPW %r2,4(%r8) # Yes, do the low ones coincide too? 1c: 7f 0c BEB L3 # Yes, exit the loop 1e: 9c 08 48 L2: ADDW2 &8,%r8 # Update the address 21: 94 47 DECW %r7 # Any more members? 23: 77 ee BNEB L1 # Yes, continue with the next one 25: 84 ff 40 MOVW &-1,%r0 # No, double word in r1:r2 not found, return -1 28: 04 c9 f0 4cMOVAW -16(%fp),%spL3: RESTORE %r7 # Restore the saved registers r7,r8 2c: 20 48 POPW %r8 2e: 20 47 POPW %r7 30: 20 49 POPW %fp 32: 08 RET # Return to the calling function 33: 70 NOP 68K GAS search64.s page 1 1 | Да се напише подпрограма, която да връща в регистър D0 индекса на подадената 2 | в SP(4):SP(8) двойна дума в масива от двойни думи (BE) с начален адрес в 3 | SP(16) и брой елементи в SP(12), или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 4E56 0000 LINK %FP,#0 | Създай стекова рамка 8 0004 48E7 3C00 MOVEML %D2-%D5,-(%SP) | GCC изисква да съхраняваме D2 и следващите 9 0008 4CEE 0107 0008 MOVEML 8(%FP),%D0-%D2/%A0| D0:D1 = дв.дума, D2 = бр.елем., A0 = адрес 10 000e 5382 SUBQL #1,%D2 | Коригирай броя елементи („DBF“ стига до −1) 11 0010 76FF MOVEQ #-1,%D3 | Инициализирай индекса 12 0012 5283 L1: ADDQL #1,%D3 | Актуализирай го 13 0014 4CD8 0030 MOVEML (%A0)+,%D4/%D5 | Зареди следващата двойна дума 14 0018 B880 CMPL %D0,%D4 | Съвпадат ли старшите думи? 15 001a 6604 BNEB L2 | Не 16 001c BA81 CMPL %D1,%D5 | Да, съвпадат ли и младшите? 17 001e 6706 BEQB L3 | Да, излез от цикъла 18 0020 51CA FFF0 L2: DBF %D2,L1 | Не, продължи със следващия елемент 19 0024 76FF MOVEQ #-1,%D3 | Двойната дума в D0:D1 не е намерена, върни -1 20 0026 2003 L3: MOVEL %D3,%D0 | Върни индекса на откритата съвпадаща двойна дума 21 0028 4CDF 003C MOVEML (%SP)+,%D2-%D5 22 002c 4E5E UNLK %FP 23 002e 4E75 RTS | Върни управлението x86 NASM search64.s 1 ; Да се напише подпрограма, която да връща в регистър EAX индекса на подадената 2 ; в регистри EDX:EAX двойна дума в масива от двойни думи с начален адрес в 3 ; [ESP+4] (арг.№3) и брой елементи в регистър ECX или -1, ако не е намерена 4 5 section .text 6 global search64,_search64; в GCC декларирай с __attribute__((regparm(3))) 7 search64: 8 _search64: 9 00000000 877C2404 XCHG EDI,[ESP+4]; EDI = начален адрес (съхрани старата му стойност) 10 00000004 53 PUSH EBX ; GCC изисква EBX и EDI да се съхраняват 11 00000005 31DB XOR EBX,EBX ; Инициализирай индекса 12 00000007 3B04DF L1: CMP EAX,[EDI+8*EBX] ; Съвпадат ли младшите думи? 13 0000000A 7506 JNE L2 ; Не, прескочи сравнението на старшите 14 0000000C 3B54DF04 CMP EDX,[EDI+8*EBX+4]; Да, съвпадат ли старшите думи? 15 00000010 7406 JE L3 ; Да, излез от цикъла 16 00000012 43 L2: INC EBX ; Не, актуализирай индекса 17 00000013 E2F2 LOOP L1 18 00000015 8D59FF LEA EBX,[ECX-1]; Двойната дума в EDX:EAX не е намерена, върни -1 19 00000018 93 L3: XCHG EAX,EBX ; Върни индекса на откритата съвпадаща двойна дума 20 00000019 5B POP EBX 21 0000001A 8B7C2404 MOV EDI,[ESP+4]; Възстанови EDI 22 0000001E C3 RET ARM GAS search64.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 // в регистри R1:R0 двойна дума в масива от двойни думи (LE) с начален адрес в 3 // регистър R3 и брой елементи в регистър R2, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 70402DE9 STMFD SP!,{R4-R6,LR}//Съхрани използваните регистри (ARM IHI 0042F) 8 0004 0040E0E3 MOV R4,#-1 // Инициализирай индекса 9 0008 014084E2 L1: ADD R4,R4,#1// Актуализирай го 10 000c 6000B3E8 LDMIA R3!,{R5,R6}//Зареди следващата двойна дума 11 0010 050050E1 CMP R0,R5 // Съвпадат ли младшите думи? 12 0014 06005101 CMPEQ R1,R6 // Да, съвпадат ли и старшите? 13 0018 0200000A BEQ L2 // Да, излез от цикъла 14 001c 012052E2 SUBS R2,R2,#1// Не, продължи със следващия елемент 15 0020 F8FFFF1A BNE L1 16 0024 0040E0E3 MOV R4,#-1 // Двойната дума в R1:R0 не е намерена, върни -1 17 0028 0400A0E1 L2: MOV R0,R4 // Върни индекса на откритата съвпадаща двойна дума 18 002c 7080BDE8 LDMFD SP!,{R4-R6,PC}//Възстанови регистрите и върни управлението ARC GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r0 индекса на подадената 2 # в регистри r1:r0 двойна дума в масива от двойни думи (LE) с начален адрес в 3 # регистър r3 и брой елементи в регистър r2, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 CC77 MOV_S r6,-1 # Инициализирай индекса 8 0002 C471 L1: ADD_S r6,r6,1 # Актуализирай го 9 0004 0813 8405 LDD.AB r4,[r3,8]# Зареди следващата двойна дума 10 0008 0908 0101 BRNE r0,r4,L2 # Съвпадат ли младшите думи? 11 000c 0B09 4001 BREQ r1,r5,L3 # Да, ако старшите думи съвпадат, излез от цикъла 12 0010 8C22 7F0E L2: DBNZ r2,L1 # Не, продължи със следващия елемент 13 0014 CC77 MOV_S r6,-1 # Двойната дума в r1:r0 не е намерена, върни -1 14 0016 C040 L3: MOV_S r0,r6 # Върни индекса на откритата съвпадаща двойна дума 15 0018 E07E J_S [blink] # Върни управлението PPC GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r3 индекса на подадената 2 # в регистри r3:r4 двойна дума в масива от двойни думи (BE) с начален адрес в 3 # регистър r6 и брой елементи в регистър r5, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 38C6FFFC addi r6,r6,-4# Компенсирай автоматичното предварително увеличение 8 0004 7CA903A6 mtctr r5 # Инициализирай брояча на елементи 9 0008 38E0FFFF li r7,-1 # Инициализирай индекса 10 000c 38E70001 L1: addi r7,r7,1 # Актуализирай го 11 0010 85060004 lwzu r8,4(r6)# Зареди следващата двойна дума - първо старшата, 12 0014 85260004 lwzu r9,4(r6)# а после и младшата 13 0018 7C034040 cmplw r3,r8 # Съвпадат ли старшите думи? 14 001c 40820008 bne L2 # Не, продължи със следващия елемент 15 0020 7C044840 cmplw r4,r9 # Да, съвпадат ли и младшите? 16 0024 4002FFE8 L2: bdnzf eq,L1 # Не, продължи със следващия елемент 17 0028 41820008 beq L3 # Да, прескочи връщането на отрицателен индекс 18 002c 38E0FFFF li r7,-1 # Двойната дума в r3:r4 не е намерена, върни -1 19 0030 7CE33B78 L3: mr r3,r7 # Върни индекса на откритата съвпадаща двойна дума 20 0034 4E800020 blr # Върни управлението SPARC GAS search64.s page 1 1 ! Да се напише подпрограма, която да връща в регистър %o0 индекса на подадената 2 ! в регистри %o0:%o1 двойна дума в масива от двойни думи (BE) с начален адрес в 3 ! регистър %o3 и брой елементи в регистър %o2, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 82103FFF mov -1,%g1 ! Инициализирай индекса 8 0004 82006001 L1: add %g1,1,%g1 ! Актуализирай го 9 0008 D81AC000 ldd [%o3],%o4 ! Зареди следващата двойна дума 10 000c 9602E008 add %o3,8,%o3 ! Обнови адреса 11 0010 80A2400D cmp %o1,%o5 ! Съвпадат ли младшите думи? 12 0014 12800004 bne L2 ! Не, продължи 13 0018 80A2000C cmp %o0,%o4 ! Да, съвпадат ли и старшите? 14 001c 02800006 beq L3 ! Да, излез от цикъла 15 0020 01000000 nop 16 0024 94A2A001 L2: subcc %o2,1,%o2 ! Не, продължи със следващия елемент 17 0028 12BFFFF7 bne L1 18 002c 01000000 nop 19 0030 82103FFF mov -1,%g1 ! Двойната дума в %o0:%o1 не е намерена, върни -1 20 0034 81C3E008 L3: retl ! Изпълнява се след „mov“! 21 0038 90100001 mov %g1,%o0 ! Върни индекса на откритата съвпадаща двойна дума MIPS GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър $2 индекса на подадената 2 # в регистри $4:$5 двойна дума в масива от двойни думи (BE) с начален адрес в 3 # регистър $7 и брой елементи в регистър $6, или -1, ако не е намерена. 4 5 .ent search64 6 .global search64 7 search64: 8 0000 2402FFFF LI $2,-1 # Инициализирай индекса 9 0004 24420001 L1: ADDIU $2,$2,1 # Актуализирай го 10 0008 1046000A 00000000 BEQ $2,$6,L2 # Всички елементи вече са претърсени? Върни -1 11 0010 000250C0 SLL $10,$2,3 # Превърни индекса в адресно отместване 12 0014 01475021 ADDU $10,$10,$7 # и го добави към началния адрес на масива 13 0018 8D480004 LW $8,4($10) # Зареди следващата двойна дума - първо младшата, 14 LW $9,0($10) # а после и старшата 15 001c 14A8FFF9 8D490000 BNE $5,$8,L1 # Не съвпадат младшите думи? Виж следващия елемент 16 0024 1489FFF7 00000000 BNE $4,$9,L1 # Не съвпадат старшите " " " " " " " 17 002c 03E00008 00000000 JR $31 # Да, върни индекса на намерения съвпадащ " " 18 L2: LI $2,-1 # Двойната дума в $4:$5 не е намерена - 19 0034 03E00008 2402FFFF JR $31 # върни -1 20 003c 00000000 .end search64 RISC-V GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър a0 индекса на подадената 2 # в регистри a1:a0 двойна дума в масива от двойни думи (LE) с начален адрес в 3 # регистър a3 и брой елементи в регистър a2, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 FD58 LI a7,-1 # Инициализирай индекса 8 0002 8508 L1: ADDI a7,a7,1 # Актуализирай го 9 0004 638FC800 BEQ a7,a2,L2 # Всички елементи вече са претърсени? Върни -1 10 0008 13983800 SLLI a6,a7,3 # Превърни индекса в адресно отместване 11 000c 3698 ADD a6,a6,a3 # и го добави към началния адрес на масива 12 000e 03270800 LW a4,0(a6) # Зареди следващата двойна дума - първо младшата, 13 0012 83274800 LW a5,4(a6) # а после и старшата 14 0016 E316E5FE BNE a0,a4,L1 # Не съвпадат младшите думи? Виж следващия елемент 15 001a E394F5FE BNE a1,a5,L1 # Не съвпадат старшите " " " " " " " 16 001e 4685 MV a0,a7 # Да, върни индекса на намерения съвпадащ " " 17 0020 8280 RET 18 0022 7D55 L2: LI a0,-1 # Двойната дума в a1:a0 не е намерена - 19 0024 8280 RET # върни -1 Nios II GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 индекса на подадената 2 # в регистри r5:r4 двойна дума в масива от двойни думи (LE) с начален адрес в 3 # регистър r7 и брой елементи в регистър r6, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 C4FFBF00 MOVI r2,-1 # Инициализирай индекса 8 0004 44008010 L1: ADDI r2,r2,1 # Актуализирай го 9 0008 26078011 BEQ r2,r6,L2 # Всички елементи вече са претърсени? Върни -1 10 000c FA901410 SLLI r10,r2,3 # Превърни индекса в адресно отместване 11 0010 3A88D551 ADD r10,r10,r7 # и го добави към началния адрес на масива 12 0014 17000052 LDW r8,(r10) # Зареди следващата двойна дума - първо младшата, 13 0018 17014052 LDW r9,4(r10) # а после и старшата 14 001c 1EF93F22 BNE r4,r8,L1 # Не съвпадат младшите думи? Виж следващия елемент 15 0020 1EF87F2A BNE r5,r9,L1 # Не съвпадат старшите " " " " " " " 16 0024 3A2800F8 RET # Да, върни индекса на намерения съвпадащ " " 17 0028 C4FFBF00 L2: MOVI r2,-1 # Двойната дума в r5:r4 не е намерена - 18 002c 3A2800F8 RET # върни -1 Xtensa GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър a2 индекса на подадената 2 # в регистри a3:a2 двойна дума в масива от двойни думи (LE) с начален адрес в 3 # регистър a5 и брой елементи в регистър a4, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 7CF9 MOVI a9,-1 # Инициализирай индекса 8 0002 1B99 L1: ADDI a9,a9,1 # Актуализирай го 9 0004 471910 BEQ a9,a4,L2 # Всички елементи вече са претърсени? Върни -1 10 0007 5089B0 ADDX8 a8,a9,a5 # Добави адресното отместване към началния адрес 11 000a 6808 L32I a6,a8,0 # Зареди следващата двойна дума - първо младшата, 12 000c 7818 L32I a7,a8,4 # а после и старшата 13 000e 6792F0 BNE a2,a6,L1 # Не съвпадат младшите думи? Виж следващия елемент 14 0011 7793ED BNE a3,a7,L1 # Не съвпадат старшите " " " " " " " 15 0014 2D09 MOV a2,a9 # Да, върни индекса на намерения съвпадащ " " 16 0016 0DF0 RET 17 0018 7CF2 L2: MOVI a2,-1 # Двойната дума в a3:a2 не е намерена - 18 001a 0DF0 RET # върни -1 88K GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 индекса на подадената 2 # в регистри r2:r3 двойна дума в масива от двойни думи (BE) с начален адрес в 3 # регистър r5 и брой елементи в регистър r4, или -1, ако не е намерена. 4 5 .global _search64 6 0000 64C00001 _search64: 7 0004 60C60001 subu r6,r0,1 # Инициализирай индекса с -1 8 0008 14E50000 L1: addu r6,r6,1 # Актуализирай го 9 000c 15050004 ld r7,r5,0 # Зареди следващата двойна дума - първо старшата, 10 0010 60A50008 ld r8,r5,4 # а после и младшата 11 0014 F5227C07 addu r5,r5,8 # Обнови адреса 12 0018 D8690003 cmp r9,r2,r7# Съвпадат ли старшите думи? 13 001c F5237C08 bb1 ne,r9,L2# Не, продължи 14 0020 D8490004 cmp r9,r3,r8# Да, съвпадат ли и младшите? 15 0024 64840001 bb1 eq,r9,L3# Да, излез от цикъла 16 0028 E9A4FFF7 L2: subu r4,r4,1 # Не, продължи със следващия елемент 17 002c 64C00001 bcnd ne0,r4,L1 18 0030 F4465800 subu r6,r0,1 # Двойната дума в r2:r3 не е намерена, върни -1 19 0034 F400C001 L3: or r2,r6,r0# Върни индекса на откритата съвпадаща двойна дума jmp r1 # Върни управлението Or1k GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R11 индекса на подадената 2 # в регистри R3:R4 двойна дума в масива от двойни думи (BE) с начален адрес в 3 # регистър R6 и брой елементи в регистър R5, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 9DA0FFFF L.ADDI R13,R0,-1 # Подготви стойността за връщане, ако не е намерена 8 0004 9D60FFFF L.ADDI R11,R0,-1 # Инициализирай индекса 9 0008 9D6B0001 L1: L.ADDI R11,R11,1 # Актуализирай го 10 000c E40B2800 L.SFEQ R11,R5 # Всички елементи ли са вече претърсени? 11 0010 1000000A L.BF L2 # Да, върни -1 12 0014 B98B0003 L.SLLI R12,R11,3 # Не, превърни индекса в адресно отместване 13 0018 E18C3000 L.ADD R12,R12,R6 # и го добави към началния адрес на масива 14 001c 84EC0004 L.LWZ R7,4(R12) # Зареди следващата двойна дума - първо младшата, 15 0020 850C0000 L.LWZ R8,0(R12) # а после и старшата 16 0024 E4243800 L.SFNE R4,R7 # Съвпадат ли младшите думи? 17 0028 13FFFFF8 L.BF L1 # Не, виж следващия елемент 18 002c E4234000 L.SFNE R3,R8 # Да, съвпадат ли и старшите? 19 0030 13FFFFF6 L.BF L1 # Не, виж следващия елемент 20 0034 15000000 L.NOP 0 21 0038 44004800 L2: L.JR LR # Да, върни индекса (изпълнява се след „L.CMOV“!) 22 003c E16D580E L.CMOV R11,R13,R11 # Ако двойната дума в R3:R4 не е намерена, върни -1 Xilinx MicroBlaze GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R3 индекса на подадената 2 # в регистри R6:R5 двойна дума в масива от двойни думи (LE) с начален адрес в 3 # регистър R8 и брой елементи в регистър R7, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 FFFF60A0 ORI R3,R0,-1 # Инициализирай индекса 8 0004 01006320 L1: ADDI R3,R3,1 # Актуализирай го 9 0008 000028E9 LWI R9,R8,0 # Зареди следващата двойна дума – първо младшата, 10 000c 040048E9 LWI R10,R8,4 # а след това и старшата 11 0010 08000821 ADDI R8,R8,8 # Обнови адреса 12 0014 004C658D PCMPNE R11,R5,R9 # Съвпадат ли младшите думи? 13 0018 0C002BBC BNEI R11,L2 # Не, продължи 14 001c 0054668D PCMPNE R11,R6,R10 # Да, съвпадат ли и старшите? 15 0020 10000BBC BEQI R11,L3 # Да, излез от цикъла 16 0024 FFFFE720 L2: ADDI R7,R7,-1 # Не, продължи със следващия елемент 17 0028 DCFF27BC BNEI R7,L1 18 002c FFFF6020 ADDI R3,R0,-1 # Двойната дума в R6:R5 не е намерена, върни -1 19 0030 08000FB6 L3: RTSD R15,8 # Върни индекса на откритата съвпадаща двойна дума 20 0034 00000080 NOP HPPA GAS search64.s page 1 1 ; Да се напише подпрограма, която да връща в регистър %R28 индекса на подадена 2 ; в регистри %R25:%R26 двойна дума в масива от двойни думи (BE) с начален адрес 3 ; в регистър %R23 и брой елементи в регистър %R24, или -1, ако не е намерена. 4 5 .text 6 .global search64 7 search64: 8 0000 341C3FFF LDI -1,%R28 ; Инициализирай индекса 9 0004 B79C0002 L1: ADDI 1,%R28,%R28 ; Актуализирай го 10 0008 8B1C8022 COMBF,<<,N %R28,%R24,L2; Всички елементи вече са претърсени? Върни -1 11 000c 4EF50008 LDWM 4(%R23),%R21; Зареди старшата дума (изпълнява се преди „COMBF“) 12 0010 8AB93FDD COMBF,= %R25,%R21,L1; Не съвпадат старшите думи? Виж следващия елемент 13 0014 4EF60008 LDWM 4(%R23),%R22; Зареди младшата дума (изпълнява се преди „COMBF“) 14 0018 8ADA3FCD COMBF,= %R26,%R22,L1; Не съвпадат младшите думи? Виж следващия елемент 15 001c 0ADA2880 COMCLR,= %R26,%R22,%R0;Съвпадение: върни индекса (изп.се преди „COMBF“) 16 0020 341C3FFF L2: LDI -1,%R28 ; Двойната дума не е намерена: върни -1 17 0024 E840C002 BV,N (%R2) Renesas / SuperH SH GAS Little Endian search64.s page 1 1 ! Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 ! в регистри R5:R4 двойна дума в масива от двойни думи (LE) с начален адрес в 3 ! регистър R7 и брой елементи в регистър R6, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 FFE0 MOV #-1,R0 ! Инициализирай индекса 8 0002 0170 L1: ADD #1,R0 ! Актуализирай го 9 0004 7662 MOV.L @R7+,R2 ! Зареди следващата двойна дума – първо младшата, 10 0006 7663 MOV.L @R7+,R3 ! а след това и старшата 11 0008 4032 CMP/EQ R4,R2 ! Съвпадат ли младшите думи? 12 000a 018B BF L2 ! Не, продължи със следващия елемент 13 000c 5033 CMP/EQ R5,R3 ! Да, съвпадат ли и старшите? 14 000e 0289 BT L3 ! Да, излез от цикъла 15 0010 1046 L2: DT R6 ! Не, последен елемент? 16 0012 F68B BF L1 ! Не, продължи със следващия 17 0014 FFE0 MOV #-1,R0 ! Да, двойната дума в R5:R4 не е намерена, върни -1 18 0016 0B00 L3: RTS ! Върни в R0 индекса на откритата съвпадаща двойна дума 19 0018 0900 NOP GAS for CRIS search64.s page 1 1 ; Да се напише подпрограма, която да връща в регистър R10 индекса на подадената 2 ; в регистри R11:R10 двойна дума в масива от двойни думи (LE) с начален адрес в 3 ; регистър R13 и брой елементи в регистър R12, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 0000 8CE2 SUBQ 12,$SP ; Съхрани R0–R2 (ETRAX FS Designer’s Reference, стр.212 8 0002 FE2B MOVEM $R2,[$SP] 9 0004 7F22 MOVEQ -1,$R2 ; Инициализирай индекса 10 0006 0122 L1: ADDQ 1,$R2 ; Актуализирай го 11 0008 BD1F MOVEM [$R13+],$R1 ; Зареди следващата двойна дума 12 000a E0A6 CMP.D $R0,$R10 ; Съвпадат ли младшите думи? 13 000c 0820 BNE L2 ; Не, продължи 14 000e E1B6 CMP.D $R1,$R11 ; Да, съвпадат ли и старшите? 15 0010 0C30 BEQ L3 ; Да, излез от цикъла 16 0012 B005 NOP 17 0014 81C2 L2: SUBQ 1,$R12 ; Не, продължи със следващия елемент 18 0016 F120 BNE L1 19 0018 B005 NOP 20 001a 7F22 MOVEQ -1,$R2 ; Двойната дума в %o0:%o1 не е намерена, върни -1 21 001c 62A6 L3: MOVE.D $R2,$R10; Върни индекса на откритата съвпадаща двойна дума 22 001e F0B9 RET ; Възстанови съхранените регистри и върни управлението 23 0020 BE2F0000 MOVEM [$SP+],$R2; Изпълнява се преди „RET“! BFIN GAS search64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 # в регистри R1:R0 двойна дума в масива от двойни думи (LE) с начален адрес в 3 # [SP+12] -> P1 и брой елементи в регистър R2, или -1, ако не е намерена. 4 5 .global _search64 6 _search64: 7 0000 F0AC P0 = [SP + 12]; # Началният адрес се предава чрез стека 8 0002 1232 P2 = R2; # Брой елементи 9 0004 F96B P1 = -1 (X); # Инициализирай индекса 10 0006 096C L_1: P1 += 1; # Актуализирай го 11 0008 5108 CC = P1 == P2; # Всички елементи вече са претърсени? 12 000a 0918 IF CC JUMP L_2; # Да, върни -1 13 000c 0390 R3 = [P0++]; # Зареди младшата дума на текущия елемент 14 000e 1808 CC = R0 == R3; # Съвпадат ли младшите думи? 15 0010 0390 R3 = [P0++]; # (зареди старшата дума на " " " ") 16 0012 FA13 IF !CC JUMP L_1;# Не, виж следващия елемент 17 0014 1908 CC = R1 == R3; # Съвпадат ли старшите думи? 18 0016 F813 IF !CC JUMP L_1;# Не, виж следващия елемент 19 0018 4130 R0 = P1; # Да, върни индекса на намерения съвпадащ елемент 20 001a 1000 RTS; 21 001c F863 L_2: R0 = -1 (X); # Двойната дума в R1:R0 не е намерена - 22 001e 1000 RTS; # върни -1 Hexagon GAS search64.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 // в регистри R1:R0 двойна дума в масива от двойни думи (LE) с начален адрес в 3 // регистър R3 и брой елементи в регистър R2, или -1, ако не е намерена. 4 5 .global search64 6 search64: 7 { P0 = CMP.EQ(R0,R0)//P0 = истина 8 LOOP0 (L1,R2) // Начало и брой итерации на цикъла 9 0000 18400260 004000F2 06C00078 R6 = #0 } // Инициализирай индекса 10 000c 24E0C39B L1: IF (P0) R5:4 = MEMD(R3++#8) // Зареди следващата двойна дума 11 0010 01C480D2 P1 = CMP.EQ(R1:0,R5:4) // Съвпадат ли двойните думи? 12 0014 06C1005C IF (P1) JUMP L2 // Да, излез от цикъла 13 0018 268006B0 00C0007F { R6 = ADD(R6,#1) }:ENDLOOP0// Не, актуализирай индекса и продължи 14 L2: { IF (!P1) R0 = #-1 // Двойната дума в R1:R0 не е намерена, върни -1 15 IF (P1) R0 = R6 // Върни индекса на откритата съвпадаща двойна дума 16 0020 E05FAF7E 00409F52 00C02674 JUMPR LR } S/390 GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър 2 индекса на подадената 2 # пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри 3 и 4, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е 2, масивът x е 3, размерът n е 4 (по условие); 21 # долният индекс l е 5, горният u е 6, средният m е 7 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 9067F008 STM 6,7,8(15) # Съхрани използваните регистри (LNUX-1007-02) 26 0004 1755 XR 5,5 # l = 0; 27 0006 1864 LR 6,4 # u = n 28 0008 A76AFFFF AHI 6,-1 # - 1; 29 000c 1556 L1: CLR 5,6 30 000e A724001B JH L4 # while (l <= u) { 31 0012 41756000 LA 7,0(5,6) # m = (l + u) 32 0016 88700001 SRL 7,1 # / 2; // l и u < 2^30 33 001a 1817 LR 1,7 # Превърни индекса в адресно отместване 34 001c 89100002 SLL 1,2 35 0020 59231000 C 2,0(3,1) # if (x[m] < t) 36 0024 A7D40006 JNH L2 37 0028 41507001 LA 5,1(7) # l = m + 1; 38 002c A7F4FFF0 J L1 39 0030 A7740005 L2: JNE L3 40 0034 1827 LR 2,7 # else if (x[m] == t) 41 0036 A7F40009 J L5 # return m; 42 003a 1867 L3: LR 6,7 # else /* x[m] > t */ u = m 43 003c A76AFFFF AHI 6,-1 # - 1; 44 0040 A7F4FFE6 J L1 # } 45 0044 A728FFFF L4: LHI 2,-1 # return -1; 46 0048 9867F008 L5: LM 6,7,8(15) # Възстанови съхранените регистри 47 004c 07FE0707 BR 14 # Върни управлението ==> id32/binsrch.s <== 1 * Return in register 0 the index of the word in 7(0) in the signed word array 2 * sorted in ascending order starting at 7(4) and having 7(8) members, or -1 if 3 * not found. 4 5 *int binarySearch(int t, int *x, unsigned n) /* From the book "Programming */ 6 *{ /* Pearls" by John Louis Bentley (n, */ 7 * unsigned l = 0, u = n - 1, m; /* l, u and m are of type int there) */ 8 * while (l <= u) { 9 * m = (l + u) / 2; /* Danger of overflow (JDK-5045582)! */ 10 * if (x[m] < t) 11 * l = m + 1; 12 * else if (x[m] == t) 13 * return m; 14 * else /* x[m] > t */ 15 * u = m - 1; 16 * } 17 * return -1; 18 *} 19 20 * Word searched for t is 7(0), array x is 7(4), size n is 7(8) by definition; 21 * lower index l is reg.3, upper index u reg.4, middle index m reg.0 (by choice) 22 23 entry binsrch 00000000d 24 binsrch equ * 00000d 5817 0000 25 l 1,0(7) t 00004d 5827 0004 26 l 2,4(7) x 00008d 0733 27 xr 3,3 l = 0; 0000Ad 5847 0008 28 l 4,8(7) u = n 0000Ed 2741 29 sis 4,1 - 1; 00010d 0943 30 L1 cr 4,3 00012d 2383 00000018d 31 bnls L2 while (l <= u) { 00014d 2501 32 lcs 0,1 ____ 00016d 030F 33 br 15 ____|_ 00018d E603 4400 0000 34 L2 la 0,0(3,4) | | m = (l + u) 0001Ed 1001 35 srls 0,1 | | / 2;// l,u < 2^18 (7,8/32) 00020d 0850 36 lr 5,0 m | | 00022d 1152 37 slls 5,2 4*m | | 00024d 5912 4500 0000 38 c 1,0(2,5) | | if (x[m] < t) 0002Ad 033F 39 ber 15 __ | |_____________________ 0002Cd 2115 00000036d 40 bms L3 |_|______ | 0002Ed 0830 41 lr 3,0 | \ l = m | 00030d 2631 42 ais 3,1 | \ + 1; V 00032d 4300 FFDA 00000010d 43 b L1(0) | else if (x[m] == t) return m; 00036d 0840 44 L3 lr 4,0 | else /* x[m] > t */ u = m 00038d 2741 45 sis 4,1 V - 1; 0003Ad 4300 FFD2 00000010d 46 b L1(0) } return -1; VAX GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 # в AP(4) дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в AP(8) и AP(12), а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ-*/ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е AP(4), масивът x е AP(8), размерът n е AP(12) по условие; 21 # долният индекс l е R2, горният u е R3, средният m е R4 (по избор). 22 23 .global _binsrch 24 _binsrch: 25 0000 1C00 .word 0x1C # R2-R4 26 0002 7DAC0450 MOVQ 4(AP),R0 # R0 = t, R1 = x 27 0006 D452 CLRL R2 # l = 0; 28 0008 C301AC0C 53 SUBL3 $1,12(AP),R3 # u = n - 1; 29 000d F1530052 0B00 L1: ACBL R3,$0,R2,L3 # while (l <= u) { 30 0013 D08FFFFF FFFF54 MOVL $-1,R4 #___ 31 001a D05450 L2: MOVL R4,R0 #___|_ 32 001d 04 RET # | | 33 001e C1525354 L3: ADDL3 R2,R3,R4 # | | m = (l + u) 34 0022 788FFF54 54 ASHL $-1,R4,R4 # | | / 2;// l и u < 2^30 35 0027 D1446150 CMPL (R1)[R4],R0 # | | if (x[m] < t) 36 002b 13ED BEQL L2 #_ | |_____________________ 37 002d 1406 BGTR L4 # |_|_______ | 38 002f C1015452 ADDL3 $1,R4,R2 # | \ l = m + 1; V 39 0033 11D8 BRB L1 # | else if (x[m] == t) return m; 40 0035 C3015453 L4: SUBL3 $1,R4,R3 # V else /* x[m] > t */ u = m - 1; 41 0039 11D201 BRB L1 # } return -1; ==> we32k/binsrch.s <== # Return in the r0 register the index of the word in ap(0) in the signed word # array sorted in ascending order starting at ap(4) and having ap(8) members, # or -1 if not found. #int binarySearch(int t, int *x, unsigned n) /* From the book "Programming */ #{ /* Pearls" by John Louis Bentley (n, */ # unsigned l = 0, u = n - 1, m; /* l, u and m are of type int there) */ # while (l <= u) { # m = (l + u) / 2; /* Danger of overflow (JDK-5045582)! */ # if (x[m] < t) # l = m + 1; # else if (x[m] == t) # return m; # else /* x[m] > t */ # u = m - 1; # } # return -1; #} # Word searched for t is ap(0), array x is ap(4), size n is ap(8) by definition # lower index l is r6, upper index u is r7, middle index m is r0 (by choice). section .text .globl binsrch binsrch() binsrch: 0: 10 46 SAVE %r6 # r6-r8 2: 84 5a 41 MOVW 0(%ap),%r1 # t 5: 84 74 42 MOVW 4(%ap),%r2 # x 8: 70 NOP 9: 80 46 CLRW %r6 # l = 0; b: fc 01 78 47 SUBW3 &1,8(%ap),%r7 # u = n - 1; f: 3c 47 46 L1: CMPW %r7,%r6 12: 5f 12 BLEUB L3 # while (l <= u) { 14: 84 ff 40 MOVW &-1,%r0 #___ 17: 04 c9 f4 4cMOVAW -12(%fp),%spL2: RESTORE %r6 #___|_ 1b: 20 48 POPW %r8 1d: 20 47 POPW %r7 1f: 20 46 POPW %r6 21: 20 49 POPW %fp 23: 08 RET # | | 24: dc 46 47 40 L3: ADDW3 %r6,%r7,%r0 # | | m = (l + u) 28: d4 01 40 40 LRSW3 &1,%r0,%r0 # | | / 2;// l and u < 2^30 2c: d0 02 40 48 LLSW3 &2,%r0,%r8 #4*m | | 30: 9c 42 48 ADDW2 %r2,%r8 #&x[m] | | 33: 3c 41 58 CMPW %r1,(%r8) # | | if (x[m] < t) 36: 7f e1 BEB L2 #_ | |_____________________ 38: 47 08 BGB L4 # |_|_______ | 3a: dc 01 40 46 ADDW3 &1,%r0,%r6 # | \ l = m + 1; V 3e: 7b d1 BRB L1 # | else if (x[m] == t) return m; 40: fc 01 40 47 L4: SUBW3 &1,%r0,%r7 # V else /* x[m] > t */ u = m - 1; 44: 7b cb BRB L1 # } return -1; 46: 70 NOP 47: 70 NOP 68K GAS binsrch.s page 1 1 | Да се напише подпрограма, която да връща в регистър D0 индекса на подадената 2 | в SP(4) дума в сортирания във възходящ ред масив от думи със знак с начален 3 | адрес и брой елементи съответно в SP(8) и SP(12), а ако не е намерена, -1. 4 5 |int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ-*/ 6 |{ /* мирането" от Джон Луис Бентли */ 7 | unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 | while (l <= u) { 9 | m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 | if (x[m] < t) 11 | l = m + 1; 12 | else if (x[m] == t) 13 | return m; 14 | else /* x[m] > t */ 15 | u = m - 1; 16 | } 17 | return -1; 18 |} 19 20 | Търсената дума t е SP(4), масивът x е SP(8), размерът n е SP(12) по условие; 21 | долният индекс l е D2, горният u е D3, средният m е D0 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 4CEF 0302 0004 MOVEML 4(%SP),%D1/%A0-%A1 | D1 = t, A0 = x, A1 = n 26 0006 48E7 3000 MOVEML %D2-%D3,-(%SP) | // GCC изисква да съхраняваме D2 и следващите 27 000a 4282 CLRL %D2 | l = 0; 28 000c C789 EXG %A1,%D3 | u = n 29 000e 5383 SUBQL #1,%D3 | - 1; 30 0010 B483 L1: CMPL %D3,%D2 31 0012 621A BHIB L4 | while (l <= u) { 32 0014 2002 L2: MOVEL %D2,%D0 | m = (l 33 0016 D083 ADDL %D3,%D0 | + u) 34 0018 E290 ROXRL #1,%D0 | / 2;// Избегни препълване! 35 001a B2B0 0C00 CMPL (%A0,%D0*4),%D1 | if (x[m] < t) 36 001e 6710 BEQB L5 |-->_________________ 37 0020 6D06 BLTB L3 | 38 0022 2400 MOVEL %D0,%D2 | l = m 39 0024 5282 ADDQL #1,%D2 | V + 1; 40 0026 60E8 BRAB L1 | else if (x[m] == t) return m; 41 0028 2600 L3: MOVEL %D0,%D3 | else /* x[m] > t */ u = m 42 002a 5383 SUBQL #1,%D3 | - 1; 43 002c 60E2 BRAB L1 | } 44 002e 70FF L4: MOVEQ #-1,%D0 | return -1; 45 0030 4CDF 000C L5: MOVEML (%SP)+,%D2-%D3 | // Възстанови съхранените регистри и върни 46 0034 4E75 RTS | // в D0 индекса на намерената дума или −1 x86 NASM binsrch.s 1 ; Да се напише подпрограма, която да връща в регистър EAX индекса на подадената 2 ; в EAX дума в сортирания във възходящ ред масив от думи със знак с начален 3 ; адрес и брой елементи съответно в EDX и ECX, а ако не е намерена, -1. 4 5 ;int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 ;{ /* мирането" от Джон Луис Бентли */ 7 ; unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 ; while (l <= u) { 9 ; m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 ; if (x[m] < t) 11 ; l = m + 1; 12 ; else if (x[m] == t) 13 ; return m; 14 ; else /* x[m] > t */ 15 ; u = m - 1; 16 ; } 17 ; return -1; 18 ;} 19 20 ; Търсената дума t е в EAX->EDI, адресът на масива x е в EDX, размерът n в ECX; 21 ; долният индекс l е в ESI, горният u е в ECX, а средният m е в EAX (по избор). 22 23 section .text 24 global binsrch,_binsrch ;в GCC декларирай с __attribute__((regparm(3))) 25 binsrch: 26 _binsrch: 27 00000000 56 PUSH ESI ; GCC изисква ESI и EDI да се съхраняват 28 00000001 57 PUSH EDI 29 00000002 97 XCHG EAX,EDI ; t 30 00000003 31F6 XOR ESI,ESI ; l = 0; 31 00000005 49 DEC ECX ; u = n - 1; 32 00000006 39F1 L1: CMP ECX,ESI 33 00000008 7216 JB L3 ; while (l <= u) { 34 0000000A 8D0431 LEA EAX,[ECX+ESI] ; m = (l + u) 35 0000000D D1E8 SHR EAX,1 ; / 2; // без знак 36 0000000F 393C82 CMP [EDX+4*EAX],EDI 37 00000012 7D05 JGE L2 ; if (x[m] < t) 38 00000014 8D7001 LEA ESI,[EAX+1] ; l = m + 1; 39 00000017 EBED JMP L1 ; ___ else if (x[m] == t) 40 00000019 7407 L2: JE L4 ;__/ return m; 41 0000001B 8D48FF LEA ECX,[EAX-1] ; else /* x[m] > t */ u = m - 1; 42 0000001E EBE6 JMP L1 ; } 43 00000020 19C0 L3: SBB EAX,EAX ; return -1; 44 00000022 5F L4: POP EDI 45 00000023 5E POP ESI 46 00000024 C3 RET ARM GAS binsrch.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 2 // пак там дума в сортирания във възходящ ред масив от д 3 // адрес и брой елементи съответно в регистри R1 и R2, а ак 4 5 //int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ 6 //{ /* мирането" от Джон Луис Бентли */ 7 // unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 // while (l <= u) { 9 // m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 // if (x[m] < t) 11 // l = m + 1; 12 // else if (x[m] == t) 13 // return m; 14 // else /* x[m] > t */ 15 // u = m - 1; 16 // } 17 // return -1; 18 //} 19 20 // Търсената дума t е R0, масивът x е R1, размерът n е R2 (по ус 21 // долният индекс l е R3, горният u е R4, средният m е R5 (по из 22 23 .global binsrch 24 binsrch: 25 0000 70402DE9 STMFD SP!,{R4-R6,LR}//Съхрани използваните регистри (ARM IHI 0042F) 26 0004 0030A0E3 MOV R3,#0 // l = 0; 27 0008 014042E2 SUB R4,R2,#1 // u = n - 1; 28 000c 040053E1 L1: CMP R3,R4 29 0010 0700008A BHI L2 // while (l <= u) { 30 0014 045093E0 ADDS R5,R3,R4 // m = (l + u) 31 0018 6550A0E1 MOV R5,R5,RRX // / 2;// Избегни препълване! 32 001c 056191E7 LDR R6,[R1,R5,LSL #2] 33 0020 000056E1 CMP R6,R0 // if (x[m] < t) 34 0024 013085B2 ADDLT R3,R5,#1 // l = m + 1; 35 0028 0500A001 MOVEQ R0,R5 // else if (x[m] == t) return m; 36 002c 014045C2 SUBGT R4,R5,#1 // else /* x[m] > t */ u = m - 1; 37 0030 F5FFFF1A BNE L1 // } 38 0034 0000E013 L2: MOVNE R0,#-1 // return -1; 39 0038 7080BDE8 LDMFD SP!,{R4-R6,PC}//Възстанови регистрите и върни управление ARC GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър r0 индекса на подадената 2 # пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри r1 и r2, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ-*/ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е r0, масивът x е r1, размерът n е r2 (по условие); 21 # долният индекс l е r3, горният u е r4, средният m е r5 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 6C70 MOV_S r3,0 # l = 0; 26 0002 4222 4400 SUB r4,r2,1 # u = n - 1; 27 0006 270C C400 L1: BRLO r4,r3,L3 # while (l <= u) { 28 000a 0023 0581 ADD.F r5,r3,r4 # m = (l + u) 29 000e 2F25 4401 RRC r5,r5 # / 2;// Избегни препълване! 30 0012 F021 4601 LD.AS r6,[r1,r5] 31 0016 0D0E 0300 BRGE r6,r0,L2 # if (x[m] < t) 32 001a 4025 4300 ADD r3,r5,1 # l = m + 1; 33 001e F5F1 B_S L1 34 0020 0F0E 0000 L2: BREQ r6,r0,L4 # else if (x[m] == t) return m; 35 0024 4225 4400 SUB r4,r5,1 # else /* x[m] > t */ u = m - 1; 36 0028 EFF1 B_S L1 # } 37 002a 8A25 FF0F L3: MOV r5,-1 # return -1; 38 002e A040 L4: MOV_S r0,r5 39 0030 E07E J_S [blink] # Върни управлението PPC GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър r3 индекса на подадената 2 # пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри r4 и r5, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е r3, масивът x е r4, размерът n е r5 (по условие); 21 # долният индекс l е r6, горният u е r7, средният m е r8 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 38C00000 li r6,0 # l = 0; 26 0004 38E5FFFF addi r7,r5,-1 # u = n - 1; 27 0008 7C063840 L1: cmplw r6,r7 28 000c 41810038 bgt L4 # while (l <= u) { 29 0010 7D063A14 add r8,r6,r7 # m = (l + u) 30 0014 5508F87E srwi r8,r8,1 # / 2; // l и u < 2^30 31 0018 550A103A slwi r10,r8,2 # Превърни индекса в адресно отместване 32 001c 7D24502E lwzx r9,r4,r10 33 0020 7C091800 cmpw r9,r3 # if (x[m] < t) 34 0024 4080000C bge L2 35 0028 38C80001 addi r6,r8,1 # l = m + 1; 36 002c 4BFFFFDC b L1 37 0030 4082000C L2: bne L3 38 0034 7D034378 mr r3,r8 # else if (x[m] == t) 39 0038 4E800020 blr # return m; 40 003c 38E8FFFF L3: addi r7,r8,-1 # else /* x[m] > t */ u = m - 1; 41 0040 4BFFFFC8 b L1 # } 42 0044 3860FFFF L4: li r3,-1 # return -1; 43 0048 4E800020 blr # Върни управлението SPARC GAS binsrch.s page 1 1 ! Да се напише подпрограма, която да връща в регистър %o0 индекса на подадената 2 ! пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 ! адрес и брой елементи съответно в регистри %o1 и %o2, а ако не е намерена, -1 4 5 !int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 !{ /* мирането" от Джон Луис Бентли */ 7 ! unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 ! while (l <= u) { 9 ! m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 ! if (x[m] < t) 11 ! l = m + 1; 12 ! else if (x[m] == t) 13 ! return m; 14 ! else /* x[m] > t */ 15 ! u = m - 1; 16 ! } 17 ! return -1; 18 !} 19 20 ! Търсената дума t е %o0, масивът x е %o1, размерът n е %o2 (по условие); 21 ! долният индекс l е %o3, горният u е %o4, средният m е %o5 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 96102000 mov 0,%o3 ! l = 0; 26 0004 9822A001 sub %o2,1,%o4 ! u = n - 1; 27 0008 80A2C00C L1: cmp %o3,%o4 28 000c 18800010 bgu L4 ! while (l <= u) { 29 0010 9A02C00C add %o3,%o4,%o5 ! m = (l + u) 30 0014 9B336001 srl %o5,1,%o5 ! / 2; // l и u < 2^30 31 0018 832B6002 sll %o5,2,%g1 ! Превърни индекса в адресно отместване 32 001c C2024001 ld [%o1+%g1],%g1 33 0020 80A04008 cmp %g1,%o0 ! if (x[m] < t) 34 0024 16800004 bge L2 35 0028 01000000 nop 36 002c 10BFFFF7 ba L1 ! След „add“! 37 0030 96036001 add %o5,1,%o3 ! l = m + 1; 38 0034 12800004 L2: bne L3 39 0038 01000000 nop 40 003c 81C3E008 retl ! След „mov“! 41 0040 9010000D mov %o5,%o0 ! else if (x[m] == t) return m; 42 0044 10BFFFF1 L3: ba L1 ! След „sub“! 43 0048 98236001 sub %o5,1,%o4 ! else /* x[m] > t */ u = m - 1; 44 004c 81C3E008 L4: retl ! След „mov“! } 45 0050 90103FFF mov -1,%o0 ! return -1; MIPS GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър $2 индекса на подадената 2 # в рег. $4 дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри $5 и $6, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е $4, масивът x е $5, размерът n е $6 (по условие); 21 # долният индекс l е $7, горният u е $8, средният m е $9 (по избор). 22 23 .ent binsrch 24 .global binsrch 25 binsrch: 26 0000 24070000 LI $7,0 # int l = 0; 27 0004 24C8FFFF ADDIU $8,$6,-1 # int u = n - 1; 28 0008 0107082A 14200011 00000000 L1: BGT $7,$8,L4 # while (l <= u) { // l и u < 2^30 29 0014 00E84821 ADDU $9,$7,$8 # int m = (l + u) 30 0018 00094842 SRL $9,$9,1 # / 2;// " " " 31 001c 00095880 SLL $11,$9,2 # Превърни индекса в адресно отместване 32 0020 01655821 ADDU $11,$11,$5 # и го добави към началния адрес на масива 33 0024 8D6A0000 LW $10,0($11) 34 0028 0144082A 10200003 00000000 BGE $10,$4,L2 # if (x[m] < t) 35 ADDIU $7,$9,1 # l = m + 1; 36 0034 1000FFF4 25270001 B L1 37 003c 15440003 00000000 L2: BNE $10,$4,L3 # else if (x[m] == t) 38 MOVE $2,$9 # return m; 39 0044 03E00008 01201021 JR $31 40 L3: ADDIU $8,$9,-1 # else /* x[m] > t */ u = m - 1; 41 004c 1000FFEE 2528FFFF B L1 # } 42 L4: LI $2,-1 # return -1; 43 0054 03E00008 2402FFFF JR $31 # Върни управлението 44 005c 00000000 .end binsrch RISC-V GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър a0 индекса на подадената 2 # пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри a1 и a2, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е a0, масивът x е a1, размерът n е a2 (по условие); 21 # долният индекс l е a3, горният u е a4, средният m е a5 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 93060000 MV a3,x0 # int l = 0; 26 0004 1307F6FF ADDI a4,a2,-1 # int u = n - 1; 27 0008 6346D702 L1: BGT a3,a4,L4 # while (l <= u) { // l и u < 2^30 28 000c B387E600 ADD a5,a3,a4 # int m = (l + u) 29 0010 8583 SRLI a5,a5,1 # / 2;// " " " 30 0012 93982700 SLLI a7,a5,2 # Превърни индекса в адресно отместване 31 0016 AE98 ADD a7,a7,a1 # и го добави към началния адрес на масива 32 0018 03A80800 LW a6,0(a7) 33 001c 6355A800 BGE a6,a0,L2 # if (x[m] < t) 34 0020 93861700 ADDI a3,a5,1 # l = m + 1; 35 0024 D5B7 J L1 36 0026 6314A800 L2: BNE a6,a0,L3 # else if (x[m] == t) 37 002a 3E85 MV a0,a5 # return m; 38 002c 8280 RET 39 002e 1387F7FF L3: ADDI a4,a5,-1 # else /* x[m] > t */ u = m - 1; 40 0032 D9BF J L1 # } 41 0034 7D55 L4: LI a0,-1 # return -1; 42 0036 8280 RET # Върни управлението Nios II GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 индекса на подадената 2 # в рег. r4 дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри r5 и r6, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е r4, масивът x е r5, размерът n е r6 (по условие); 21 # долният индекс l е r7, горният u е r8, средният m е r9 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 1400C001 MOVUI r7,0 # int l = 0; 26 0004 C4FF3F32 SUBI r8,r6,1 # int u = n - 1; 27 0008 160DC041 L1: BGT r7,r8,L4 # while (l <= u) { // l и u < 2^30 28 000c 3A88133A ADD r9,r7,r8 # int m = (l + u) 29 0010 7AD01248 SRLI r9,r9,1 # / 2;// " " " 30 0014 BA901648 SLLI r11,r9,2 # Превърни индекса в адресно отместване 31 0018 3A885759 ADD r11,r11,r5 # и го добави към началния адрес на масива 32 001c 1700805A LDW r10,(r11) 33 0020 0E020051 BGE r10,r4,L2 # if (x[m] < t) 34 0024 4400C049 ADDI r7,r9,1 # l = m + 1; 35 0028 06F73F00 BR L1 36 002c 1E020051 L2: BNE r10,r4,L3 # else if (x[m] == t) 37 0030 3A880548 MOV r2,r9 # return m; 38 0034 3A2800F8 RET 39 0038 C4FF3F4A L3: SUBI r8,r9,1 # else /* x[m] > t */ u = m - 1; 40 003c 06F23F00 BR L1 # } 41 0040 C4FFBF00 L4: MOVI r2,-1 # return -1; 42 0044 3A2800F8 RET # Върни управлението Xtensa GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър a2 индекса на подадената 2 # пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри a3 и a4, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е a2, масивът x е a3, размерът n е a4 (по условие); 21 # долният индекс l е a5, горният u е a6, средният m е a7 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 0C05 MOVI a5,0 # int l = 0; 26 0002 0B64 ADDI a6,a4,-1 # int u = n - 1; 27 0004 57261D L1: BLT a6,a5,L4 # while (l <= u) { // l и u < 2^30 28 0007 6A75 ADD a7,a5,a6 # int m = (l + u) 29 0009 707141 SRLI a7,a7,1 # / 2;// " " " 30 000c 3097A0 ADDX4 a9,a7,a3 #Добави адресното отместване към началния адрес 31 000f 8809 L32I a8,a9,0 32 0011 27A804 BGE a8,a2,L2 # if (x[m] < t) 33 0014 1B57 ADDI a5,a7,1 # l = m + 1; 34 0016 86FAFF J L1 35 0019 279803 L2: BNE a8,a2,L3 # else if (x[m] == t) 36 001c 2D07 MOV a2,a7 # return m; 37 001e 0DF0 RET 38 0020 0B67 L3: ADDI a6,a7,-1 # else /* x[m] > t */ u = m - 1; 39 0022 86F7FF J L1 # } 40 0025 7CF2 L4: MOVI a2,-1 # return -1; 41 0027 0DF0 RET #Върни управлението 88K GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 индекса на подадената 2 # пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри r3 и r4, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е r2, масивът x е r3, размерът n е r4 (по ус? 21 # долният индекс l е r5, горният u е r6, средният m е r7 (по из? 22 23 .global _binsrch 24 0000 F4A05800 _binsrch: 25 0004 64C40001 or r5,r0,r0 # l = 0; 26 0008 F5057C06 subu r6,r4,1 # u = n - 1; 27 000c D908000D L1: cmp r8,r5,r6 28 0010 F4E56006 bb1 hi,r8,L4 # while (l <= u) { 29 0014 F0E79801 addu r7,r5,r6 # m = (l + u) 30 0018 F5031607 extu r7,r7,0<1> # / 2; // l и u < 2^30 31 001c F5287C02 ld r8,r3[r7] 32 0020 D8E90003 cmp r9,r8,r2 # if (x[m] < t) 33 0024 60A70001 bb1 ge,r9,L2 34 0028 C3FFFFF8 addu r5,r7,1 # l = m + 1; 35 002c D8690003 br L1 36 0030 F4475800 L2: bb1 ne,r9,L3 37 0034 F400C001 or r2,r7,r0 # else if (x[m] == t) 38 0038 64C70001 jmp r1 # return m; 39 003c C3FFFFF3 L3: subu r6,r7,1 # else /* x[m] > t */ u = m - 1; 40 0040 64400001 br L1 # } 41 0044 F400C001 L4: subu r2,r0,1 # return -1; jmp r1 # Върни управлението Or1k GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър R11 индекса на подадената 2 # в рег. R3 дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри R4 и R5, а ако не е намерена, -1 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е R3, масивът x е R4, размерът n е R5 (по условие); 21 # долният индекс l е R6, горният u е R7, средният m е R11 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 E0C00004 L.OR R6,R0,R0 # l = 0; 26 0004 9CE5FFFF L.ADDI R7,R5,-1 # u = n - 1; 27 0008 E4A63800 L1: L.SFLEU R6,R7 28 000c 0C000010 L.BNF L3 # while (l <= u) { 29 0010 E1663800 L.ADD R11,R6,R7 # m = (l + u) 30 0014 B96B0041 L.SRLI R11,R11,1 # / 2; // l и u < 2^30 31 0018 B98B0002 L.SLLI R12,R11,2 # Превърни индекса в адресно отместване 32 001c E18C2000 L.ADD R12,R12,R4 # и го добави към началния адрес на масива 33 0020 858C0000 L.LWZ R12,0(R12) 34 0024 E58C1800 L.SFLTS R12,R3 # if (x[m] < t) 35 0028 0C000004 L.BNF L2 36 002c 15000000 L.NOP 0 37 0030 03FFFFF6 L.J L1# След „L.ADDI“ 38 0034 9CCB0001 L.ADDI R6,R11,1 # l = m + 1; 39 0038 E40C1800 L2: L.SFEQ R12,R3 # else if (x[m] == t) 40 003c 10000005 L.BF L4 # return m; 41 0040 15000000 L.NOP 0 42 0044 03FFFFF1 L.J L1# След „L.ADDI“ 43 0048 9CEBFFFF L.ADDI R7,R11,-1 # else /* x[m] > t */ u = m - 1; 44 004c 9D60FFFF L3: L.ADDI R11,R0,-1 # } return -1; 45 0050 44004800 L4: L.JR LR 46 0054 15000000 L.NOP 0 Xilinx MicroBlaze GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър R3 индекса на подадената 2 # в рег. R5 дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри R6 и R7, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е R5, масивът x е R6, размерът n е R7 (по условие); 21 # долният индекс l е R8, горният u е R9, средният m е R3 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 00000081 OR R8,R0,R0 # l = 0; 26 0004 FFFF2721 ADDI R9,R7,-1 # u = n - 1; 27 0008 03488814 L1: CMPU R4,R8,R9 28 000c 340044BC BLTI R4,L3 # while (l <= u) { 29 0010 00486800 ADD R3,R8,R9 # m = (l + u) 30 0014 21006390 SRC R3,R3 # / 2; // без знак 31 0018 02048364 BSLLI R4,R3,2 # Превърни индекса в адресно отместване 32 001c 002086C8 LW R4,R6,R4 33 0020 01204515 CMP R10,R5,R4 # if (x[m] < t) 34 0024 0C00AABC BGEI R10,L2 35 0028 01000321 ADDI R8,R3,1 # l = m + 1; 36 002c DCFF00B8 BRI L1 37 0030 0024458D L2: PCMPNE R10,R5,R4#При R5 = -2^31 и R4 = 0 „CMP R10,R5,R4“ дава R10 = 0! 38 0034 10000ABC BEQI R10,L4 # else if (x[m] == t) return m; 39 0038 FFFF2321 ADDI R9,R3,-1 # else /* x[m] > t */ u = m - 1; 40 003c CCFF00B8 BRI L1 # } 41 0040 FFFF6020 L3: ADDI R3,R0,-1 # return -1; 42 0044 08000FB6 L4: RTSD R15,8 # Върни управлението 43 0048 00000080 NOP HPPA GAS binsrch.s page 1 1 ; Да се напише подпрограма, която да връща в регистър %R28 индекса на подадена 2 ; в %R26 дума в сортирания във възходящ ред масив от думи със знак с начален 3 ; адрес и брой елементи съответно в %R25 и %R24, а ако не е намерена, -1. 4 5 ;int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ-*/ 6 ;{ /* мирането" от Джон Луис Бентли */ 7 ; unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 ; while (l <= u) { 9 ; m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 ; if (x[m] < t) 11 ; l = m + 1; 12 ; else if (x[m] == t) 13 ; return m; 14 ; else /* x[m] > t */ 15 ; u = m - 1; 16 ; } 17 ; return -1; 18 ;} 19 20 ; Търсената дума t е %R26, масивът x е %R25, размерът n е %R24 по условие; 21 ; долният индекс l е %R22, горният u е %R23, средният m е %2R8 (по избор). 22 23 .text 24 .global binsrch 25 binsrch: 26 0000 34160000 LDI 0,%R22 ; l = 0; 27 0004 B71707FF ADDI -1,%R24,%R23 ; u = n - 1; 28 0008 82F6A00A L1: COMBT,<<=,N %R22,%R23,L3; while (l <= u) { 29 000c 341C3FFF LDI -1,%R28 ;___ 30 0010 E840C002 L2: BV,N (%R2) ; | 31 0014 0AF6061C L3: ADD %R22,%R23,%R28 ; | m = (l + u) 32 0018 D3800BDC SHD %R0,%R28,1,%R28 ; | / 2; 33 001c 0F3C2095 LDWX,S %R28(%R25),%R21 ; | if (x[m] < t) 34 0020 83553FD5 COMBT,= %R21,%R26,L2 ;__ | 35 0024 0B557880 COMCLR,> %R21,%R26,%R0 ; \| 36 0028 B7960002 ADDI 1,%R28,%R22 ; | l = m + 1; 37 002c 0B554880 COMCLR,< %R21,%R26,%R0 ; |\_ else if (x[m] == t) return m; 38 0030 B79707FF ADDI -1,%R28,%R23 ; V else /* x[m] > t */ u = m - 1; 39 0034 E81F1F9F B,N L1 ; } return -1; Renesas / SuperH SH GAS Little Endian binsrch.s page 1 1 ! Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 ! в рег. R4 дума в сортирания във възходящ ред масив от думи със знак с начален 3 ! адрес и брой елементи съответно в регистри R5 и R6, а ако не е намерена, -1. 4 5 !int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 !{ /* мирането" от Джон Луис Бентли */ 7 ! unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 ! while (l <= u) { 9 ! m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 ! if (x[m] < t) 11 ! l = m + 1; 12 ! else if (x[m] == t) 13 ! return m; 14 ! else /* x[m] > t */ 15 ! u = m - 1; 16 ! } 17 ! return -1; 18 !} 19 20 ! Търсената дума t е R4, масивът x е R5, размерът n е R6 (по условие); 21 ! долният индекс l е R1, горният u е R2, средният m е R0 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 00E1 MOV #0,R1 ! l = 0; 26 0002 6362 MOV R6,R2 ! u = n 27 0004 FF72 ADD #-1,R2 ! - 1; 28 0006 2631 L1: CMP/HI R2,R1 29 0008 1089 BT L3 ! while (l <= u) { 30 000a 1360 MOV R1,R0 !T=0 m = (l 31 000c 2E30 ADDC R2,R0 ! + u) 32 000e 2540 ROTCR R0 ! / 2;// Избегни препълване! 33 0010 0363 MOV R0,R3 34 0012 0843 SHLL2 R3 ! // Превърни индекса в адресно отместване 35 0014 5C33 ADD R5,R3 ! // и го добави към началния адрес на масива 36 0016 3267 MOV.L @R3,R7 !x[m] 37 0018 7734 CMP/GT R7,R4 ! if (x[m] < t) 38 001a 028B BF L2 39 001c 0361 MOV R0,R1 ! l = m 40 001e 0171 ADD #1,R1 ! + 1; 41 0020 F189 BT L1 !T=1 42 0022 7034 L2: CMP/EQ R7,R4 ! else if (x[m] == t) 43 0024 0389 BT L4 ! return m; 44 0026 0362 MOV R0,R2 ! else /* x[m] > t */ u = m 45 0028 FF72 ADD #-1,R2 ! - 1; 46 002a EC8B BF L1 ! }//T=0 47 002c FFE0 L3: MOV #-1,R0 ! return -1; 48 002e 0B00 L4: RTS ! // Върни управлението 49 0030 0900 NOP GAS for CRIS binsrch.s page 1 1 ; Да се напише подпрограма, която да връща в регистър R10 индекса на подадената 2 ; пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 ; адрес и брой елементи съответно в регистри R11 и R12, а ако не е намерена, -1 4 5 ;int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 ;{ /* мирането" от Джон Луис Бентли */ 7 ; unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 ; while (l <= u) { 9 ; m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 ; if (x[m] < t) 11 ; l = m + 1; 12 ; else if (x[m] == t) 13 ; return m; 14 ; else /* x[m] > t */ 15 ; u = m - 1; 16 ; } 17 ; return -1; 18 ;} 19 20 ; Търсената дума t е $R10, масивът x е $R11, размерът n е $R12 (по условие); 21 ; долният индекс l е $R0, горният u е $R1, средният m е $R13 (по избор). 22 23 .global binsrch 24 binsrch: 25 0000 8CE2 SUBQ 12,$SP ; Съхрани R0–R2 (ETRAX FS Designer’s Reference, стр.212 26 0002 FE2B MOVEM $R2,[$SP] 27 0004 7086 CLEAR.D $R0 ; l = 0; 28 0006 6C16 MOVE.D $R12,$R1 ; u = n 29 0008 8112 SUBQ 1,$R1 ; - 1; 30 000a E106 L1: CMP.D $R1,$R0 31 000c 2490 BHI L4 ; while (l <= u) { 32 000e 60D6 MOVE.D $R0,$R13 33 0010 21D6 ADD.D $R1,$R13 ; m = (l + u) 34 0012 E1D3 LSRQ 1,$R13 ; / 2; // l и u < 2^30 35 0014 6BD5 ADDI $R13.D,$R11,$ACR; Превърни индекса в адрес 36 0016 EFAA CMP.D [$ACR],$R10 ; if (x[m] < t) 37 0018 0AD0 BLE L2 38 001a B005 NOP 39 001c 6D06 MOVE.D $R13,$R0 ; l = m 40 001e EDE0 BA L1 ;След „ADDQ“! 41 0020 0102 ADDQ 1,$R0 ; + 1; 42 0022 0820 L2: BNE L3 ; else if (x[m] == t) 43 0024 B005 NOP 44 0026 0CE0 BA L5 ;След „MOVEQ“! return 45 0028 6DA6 MOVE.D $R13,$R10 ; m; 46 002a 6D16 L3: MOVE.D $R13,$R1 ; else /* x[m] > t */ u = m 47 002c DFE0 BA L1 ;След „SUBQ“! 48 002e 8112 SUBQ 1,$R1 ; - 1; 49 0030 7FA2 L4: MOVEQ -1,$R10 ; return -1; 50 0032 F0B9 L5: RET ;След „MOVEM“!} 51 0034 BE2F0000 MOVEM [$SP+],$R2; Изпълнява се преди „RET“! BFIN GAS binsrch.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 # пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 # адрес и брой елементи съответно в регистри R1 и R2, а ако не е намерена, -1. 4 5 #int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ- */ 6 #{ /* мирането" от Джон Луис Бентли */ 7 # unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 # while (l <= u) { 9 # m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 # if (x[m] < t) 11 # l = m + 1; 12 # else if (x[m] == t) 13 # return m; 14 # else /* x[m] > t */ 15 # u = m - 1; 16 # } 17 # return -1; 18 #} 19 20 # Търсената дума t е R0, масивът x е R1 -> P0, размерът n е R2 (по условие); 21 # долният индекс l е R1, горният u е R2 (n - 1), средният m е P1 (по избор). 22 23 .global _binsrch 24 _binsrch: 25 0000 0132 P0 = R1; #Начален адрес 26 0002 0160 R1 = 0; # l = 0; 27 0004 FA67 R2 += -1; # u = n - 1; 28 0006 110A L_1: CC = R1 <= R2 (IU); # while (l <= u) { // l и u < 2^30 29 0008 1210 IF !CC JUMP L_4; 30 000a D150 R3 = R1 + R2; # m = (l + u) 31 000c 0B32 P1 = R3; 32 000e 0945 P1 = P1 >> 1; # / 2; // " " " 33 0010 885E P2 = P0 + (P1 << 2); #Добави адресното отместване към началния адрес 34 0012 1391 R3 = [P2]; 35 0014 8308 CC = R3 < R0; # if (x[m] < t) 36 0016 0410 IF !CC JUMP L_2; 37 0018 4930 R1 = P1; # l = m 38 001a 0964 R1 += 1; # + 1; 39 001c F52F JUMP L_1; 40 001e 0308 L_2: CC = R3 == R0; # else if (x[m] == t) 41 0020 0314 IF !CC JUMP L_3 (BP); 42 0022 4130 R0 = P1; # return m; 43 0024 1000 RTS; 44 0026 5130 L_3: R2 = P1; # else /* x[m] > t */ u = m 45 0028 FA67 R2 += -1; # - 1; 46 002a EE2F JUMP L_1; # } 47 002c F863 L_4: R0 = -1; # return -1; 48 002e 1000 RTS; #Върни управлението Hexagon GAS binsrch.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 индекса на подадената 2 // пак там дума в сортирания във възходящ ред масив от думи със знак с начален 3 // адрес и брой елементи съответно в регистри R1 и R2, а ако не е намерена, -1. 4 5 //int binarySearch(int t, int *x, unsigned n)/* Из книгата "Бисери на програ-*/ 6 //{ /* мирането" от Джон Луис Бентли */ 7 // unsigned l = 0, u = n - 1, m; /* (там n, l, u и m са тип int). */ 8 // while (l <= u) { 9 // m = (l + u) / 2; /* Опасност от препълване (JDK-5045582)! */ 10 // if (x[m] < t) 11 // l = m + 1; 12 // else if (x[m] == t) 13 // return m; 14 // else /* x[m] > t */ 15 // u = m - 1; 16 // } 17 // return -1; 18 //} 19 20 // Търсената дума t е R0, масивът x е R1, размерът n е R2 (по условие); 21 // долният индекс l е R3, горният u е R4, средният m е R5 (по избор). 22 23 .global binsrch 24 binsrch: 25 { R3 = #0 // l = 0; 26 0000 24330328 R4 = ADD(R2,#-1) } // u = n - 1; 27 0004 00C463F2 L1: P0 = CMP.GTU(R3,R4) 28 { IF (P0) R0 = #-1 // while (l <= u) { 29 0008 E05F0F7E 00C05F53 IF (P0) JUMPR LR }//___ 30 0010 05C403F3 R5 = ADD(R3,R4)// \ m = (l + u) 31 0014 25C1058C R5 = LSR(R5,#1)// \ / 2;// l,u < 2^31 32 0018 06E5813A R6 = MEMW(R1+R5<<#2)/*\*/ 33 001c 00C640F2 P0 = CMP.LT(R6,R0) //\ if (x[m] < t) 34 { IF (P0) R3 = ADD(R5,#1) // \ l = m + 1; 35 0020 23400574 01C006F2 P1 = CMP.EQ(R6,R0) } // \ else 36 { IF (P1) R0 = R5 // | if (x[m] == t) 37 0028 00402574 00C15F53 IF (P1) JUMPR LR } // | return m; 38 { IF (!P0) R4 = ADD(R5,#-1)// V else /* x[m] > t */ u = m - 1; 39 0030 E45F8574 EAFFFF59 JUMP L1 } // } return -1; S/390 GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър 2 и брой 3 # елементи (поне 2) в регистър 3. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 # Нека индексите на външния (i) и вътрешния цикли (j) са регистри 4 и 5. 16 17 .global inssort 18 inssort: 19 0000 A7480001 LHI 4,1 #for (int i = 1; 20 0004 1943 L1: CR 4,3 # i < toSort.size(); 21 0006 07BE BNLR 14 # Иначе край 22 0008 1854 LR 5,4 # for (int j = i 23 000a A75AFFFF L2: AHI 5,-1 # - 1; --j) 24 000e A7440013 JL L3 # j >= 0; 25 0012 1815 LR 1,5 26 0014 89100002 SLL 1,2 # Превърни индекса в адресно отместване 27 0018 1E12 ALR 1,2 # Получи адреса на toSort[j] 28 001a 58001004 L 0,4(1) # if (toSort[j+1] 29 001e 59001000 C 0,0(1) # < toSort[j]) 30 0022 A7B40009 JNL L3 #_______ 31 0026 D2031004 1000 MVC 4(4,1),0(1)# \ swap(toSort[j], toSort[j+1]); 32 002c 50001000 ST 0,0(1) # \______else break; 33 0030 A7F4FFED J L2 # Край на вътрешния цикъл 34 0034 A74A0001 L3: AHI 4,1 # ++i) 35 0038 A7F4FFE6 J L1 # Край на външния цикъл ==> id32/inssort.s <== 1 * Sort in accending order using the insertion sort algorightm an array of 2 * signed words starting at 7(0) -> reg.2 with member count (at least 2) in 7(4) 3 4 *void insertionSort(vector& toSort) // From the book "Theoretical 5 *{ // algorithms in C++" by Kevin 6 * for (int i = 1; i < toSort.size(); ++i) // de Keyser (2015) 7 * for (int j = i - 1; j >= 0; --j) 8 * if (toSort[j+1] < toSort[j]) 9 * swap(toSort[j], toSort[j+1]); 10 * else // These 2 lines aren't in the 11 * break; // aforementioned book! 12 *} 13 14 * Let the outer loop index (i) be r0, and the inner loop index (j) be r1. 15 16 entry inssort 00000000d 17 inssort equ * 00000d 5827 0000 18 l 2,0(7) 00004d 0700 19 xr 0,0 for (unsigned i = 0; 00006d 5507 0004 20 L1 cl 0,4(7) i < tSort.size(); 0000Ad 4380 8032 00000040d 21 bnc L4(0) 0000Ed 0810 22 lr 1,0 for (unsigned j = i 00010d 2711 23 L2 sis 1,1 - 1; --j) 00012d 4280 8024 0000003Ad 24 bc L3(0) j != -1; 00016d 0831 25 lr 3,1 00018d 1132 26 slls 3,2 4*i 0001Ad 5842 4300 0004 27 l 4,4(2,3) if (toSort[j+1] 00020d 5852 4300 0000 28 l 5,0(2,3) < toSort[j]) 00026d 0945 29 cr 4,5 00028d 2319 0000003Ad 30 bnms L3 ___________ 0002Ad 5042 4300 0000 31 st 4,0(2,3) \swap(toSort[j], toSort[j+1]); 00030d 5052 4300 0004 32 st 5,4(2,3) else\break; 00036d 4300 FFD6 00000010d 33 b L2(0) ^ 0003Ad 2601 34 L3 ais 0,1 ++i) 0003Cd 4300 FFC6 00000006d 35 b L1(0) ^ 00040d 030F 36 L4 br 15 VAX GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в AP(4) -> R0 и брой 3 # елементи (поне 2) в AP(8). 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 # Нека индексът на външния цикъл (i) е R1, а на вътрешния (j) е R2. 16 17 .global _inssort 18 _inssort: 19 0000 0C00 .word 0xC #R2-R3 20 0002 D0AC0450 MOVL 4(AP),R0 21 0006 D451 CLRL R1 #for (int i = 0; 22 0008 F15100AC 082500 L1: ACBL R1,$0,8(AP),L4# i < toSort.size(); 23 000f C3015152 SUBL3 $1,R1,R2# for (int j = i - 1; 24 0013 191A L2: BLSS L3 # i >= 0; 25 0015 D142A004 4260 CMPL 4(R0)[R2],(R0)[R2]# if (toSort[j+1] < toSort[j]) 26 001b 1812 BGEQ L3 #___________ 27 001d D042A004 53 MOVL 4(R0)[R2],R3# \ swap(toSort[j], toSort[j+1]); 28 0022 D0426042 A004 MOVL (R0)[R2],4(R0)[R2]#/*\*/ 29 0028 D0534260 MOVL R3,(R0)[R2]# \_else break; 30 002c F452E4 SOBGEQ R2,L2 # Край на вътрешния цикъл --j) 31 002f F3AC0851 D4 L3: AOBLEQ 8(AP),R1,L1#Край на външния цикъл ++i) 32 0034 04010101 L4: RET ==> we32k/inssort.s <== # Sort in accending order using the insertion sort algorightm an array of # signed words starting at ap(0) -> r2 with member count (at least 2) in ap(4). #void insertionSort(vector& toSort) // From the book "Theoretical #{ // algorithms in C++" by Kevin # for (int i = 1; i < toSort.size(); ++i) // de Keyser (2015) # for (int j = i - 1; j >= 0; --j) # if (toSort[j+1] < toSort[j]) # swap(toSort[j], toSort[j+1]); # else // These 2 lines aren't in the # break; // aforementioned book! #} # Let the outer loop index (i) be r0, and the inner loop index (j) be r1. section .text .globl inssort inssort() inssort: 0: 10 47 SAVE %r7 #r7-r8 2: 84 5a 42 MOVW 0(%ap),%r2 5: 70 NOP 6: 80 40 CLRW %r0 #for (unsigned i = 0; 8: 3c 74 40 L1: CMPW 4(%ap),%r0 # i < tSort.size(); b: 53 2a BGEUB L4 d: fc 01 40 41 SUBW3 &1,%r0,%r1 # for (unsigned j = i - 1; 11: 5b 20 L2: BCSB L3 # j != -1; 13: d0 02 41 47 LLSW3 &2,%r1,%r7 #4*i 17: 9c 42 47 ADDW2 %r2,%r7 #&toSort[i] 1a: 84 c7 04 48 MOVW 4(%r7),%r8 # if (toSort[j+1] 1e: 3c 57 48 CMPW (%r7),%r8 # < toSort[j]) 21: 43 10 BGEB L3 #__________ 23: 84 57 c7 04 MOVW (%r7),4(%r7) # \swap(toSort[j], toSort[j+1]); 27: 70 NOP 28: 84 48 57 MOVW %r8,(%r7) # else\break; 2b: 70 NOP 2c: bc 01 41 SUBW2 &1,%r1 # --j) 2f: 53 e2 BCCB L2 # ^ 31: 90 40 L3: INCW %r0 # ++i) 33: 7b d5 BRB L1 #^ 35: 04 c9 f0 4cMOVAW -16(%fp),%spL4: RESTORE %r7 39: 20 48 POPW %r8 3b: 20 47 POPW %r7 3d: 20 49 POPW %fp 3f: 08 RET 68K GAS inssort.s page 1 1 | Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 | вмъкването масив от думи със знак с начален адрес в SP(4) -> A0 и брой 3 | елементи (поне 2) в SP(8) -> D3. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 # Нека индексът на външния цикъл (i) е D0, а на вътрешния (j) е D1. 16 17 .global inssort 18 inssort: 19 0000 4CEF 0300 0004 MOVEML 4(%SP),%A0-%A1 | A0 = начален адрес, A1 = брой елементи 20 0006 48E7 3000 MOVEML %D2-%D3,-(%SP) | GCC изисква D2 и следващите да се съхраняват 21 000a 2609 MOVEL %A1,%D3 | D3 = брой елементи 22 000c 4280 CLRL %D0 |for (unsigned i = 0; 23 000e B083 L1: CMPL %D3,%D0 | i < toSort.size(); 24 0010 6420 BHSB L4 25 0012 2200 MOVEL %D0,%D1 | for (unsigned j = i 26 0014 5381 L2: SUBQL #1,%D1 | - 1; --j) 27 0016 6516 BCSB L3 | j != -1; 28 0018 2430 1C04 MOVEL 4(%A0,%D1*4),%D2| if (toSort[j+1] 29 001c B4B0 1C00 CMPL (%A0,%D1*4),%D2| < toSort[j]) 30 0020 6C0C BGEB L3 |__________________ 31 0022 21B0 1C00 1C04 MOVEL (%A0,%D1*4),4(%A0,%D1*4)| \ swap(toSort[j], toSort[j+1]); 32 0028 2182 1C00 MOVEL %D2,(%A0,%D1*4)| else\break; 33 002c 60E6 BRAB L2 | Край на вътрешния цикъл 34 002e 5280 L3: ADDQL #1,%D0 | ++i) 35 0030 60DC BRAB L1 | Край на външния цикъл 36 0032 4CDF 000C L4: MOVEML (%SP)+,%D2-%D3 37 0036 4E75 RTS | Край на подпрограмата x86 NASM inssort.s 1 ; Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 ; вмъкването масив от думи със знак с начален адрес в регистър EAX и брой 3 ; елементи (поне 2) в регистър EDX. 4 5 ;void insertionSort(vector& toSort) // Из книгата "Теоретични 6 ;{ // алгоритми на C++" от 7 ; for (int i = 0; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 ; for (int j = i - 1; j >= 0; --j) 9 ; if (toSort[j+1] < toSort[j]) 10 ; swap(toSort[j], toSort[j+1]); 11 ; else // Тези 2 реда ги няма в 12 ; break; // горепосочената книга! 13 ;} 14 15 ; Нека индексът на външния цикъл (i) е EDI, а на вътрешния (j) е EBX. 16 17 section .text 18 global inssort,_inssort; в GCC декларирай с __attribute__((regparm(3))) 19 inssort: 20 _inssort: 21 00000000 60 PUSHAD ; GCC изисква EBX и EDI да се съхраняват 22 00000001 31FF XOR EDI,EDI ;for (unsigned i = 0; 23 00000003 39D7 L1: CMP EDI,EDX 24 00000005 731A JAE L4 ; i < toSort.size(); 25 00000007 89FB MOV EBX,EDI ; for (unsigned j = i 26 00000009 4B L2: DEC EBX ; - 1; --j) 27 0000000A 7812 JS L3 ; DEC не променя CF j != -1; 28 0000000C 8B4C9804 MOV ECX,[EAX+4*EBX+4]; if (toSort[j+1] 29 00000010 3B0C98 CMP ECX,[EAX+4*EBX]; < toSort[j]) 30 00000013 7D09 JGE L3 ;_________ 31 00000015 870C98 XCHG ECX,[EAX+4*EBX]; \ swap(toSort[j], toSort[j+1]; 32 00000018 894C9804 MOV [EAX+4*EBX+4],ECX; \____else break; 33 0000001C EBEB JMP L2 ; Край на вътрешния цикъл 34 0000001E 47 L3: INC EDI ; ++i) 35 0000001F EBE2 JMP L1 ; Край на външния цикъл 36 00000021 61 L4: POPAD 37 00000022 C3 RET ; Край на подпрограмата ARM GAS inssort.s page 1 1 // Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 // вмъкването масив от думи със знак с начален адрес в регистър R0 и брой 3 // елементи (поне 2) в регистър R1. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 // Нека индексът на външния цикъл (i) е R2, а на вътрешния (j) е R3. 16 17 .global inssort 18 inssort: 19 0000 70402DE9 STMFD SP!,{R4-R6,LR}//Съхрани използваните регистри (ARM IHI 0042F) 20 0004 0120A0E3 MOV R2,#1 //for (unsigned i = 1; 21 0008 010052E1 L1: CMP R2,R1 // i < toSort.size(); 22 000c 7080BD28 LDMHSFD SP!,{R4-R6,PC}//Възстанови регистрите и върни управлението 23 0010 0230A0E1 MOV R3,R2 // for (unsigned j = i 24 0014 013053E2 L2: SUBS R3,R3,#1// - 1; --j) 25 0018 0500003A BLO L3 // j != -1; 26 001c 036180E0 ADD R6,R0,R3,LSL #2 27 0020 300096E8 LDMIA R6,{R4,R5} 28 0024 040055E1 CMP R5,R4 // if (toSort[j+1] < toSort[j]) 29 0028 044086B5 STRLT R4,[R6,#4] 30 002c 005086B5 STRLT R5,[R6] // swap(toSort[j], toSort[j+1]); 31 0030 F7FFFFBA BLT L2 // Край на вътрешния цикъл 32 0034 012082E2 L3: ADD R2,R2,#1// else break; ++i) 33 0038 F2FFFFEA B L1 // Край на външния цикъл ARC GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър r0 и брой 3 # елементи (поне 2) в регистър r1. 4 5 /* void insertionSort(vector& toSort) # Из книгата "Теоретични 6 { # алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) # Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else # Тези 2 реда ги няма в 12 break; # горепосочената книга! 13 } */ 14 15 # Нека индексът на външния цикъл (i) е r2, а на вътрешния (j) е r3. 16 17 .global inssort 18 inssort: 19 0000 4C71 MOV_S r2,1 # for (unsigned i = 1; 20 0002 3072 L1: CMP_S r2,r1 # i < toSort.size(); 21 0004 E07C JEQ_S [blink] # Върни управлението 22 0006 4043 MOV_S r3,r2 # for (unsigned j = i 23 0008 4223 4380 L2: SUB.F r3,r3,1 # - 1; --j) 24 000c 8CF7 BLO_S L3 # j != -1; 25 000e 1520 C600 ADD2 r6,r0,r3 26 0012 0016 8401 LDD r4,[r6] 27 0016 110D 0301 BRGE r5,r4,L3# if (toSort[j+1] < toSort[j]) 28 001a 041E 0001 ST r4,[r6,4] 29 001e 001E 4001 ST r5,[r6] # swap(toSort[j], toSort[j+1]); 30 0022 F4F1 B_S L2 # Край на вътрешния цикъл 31 0024 4471 L3: ADD_S r2,r2,1 # else break; ++i) 32 0026 EFF1 B_S L1 # Край на външния цикъл PPC GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър r3 и брой 3 # елементи (поне 2) в регистър r4. 4 5 #void insertionSort(vector& toSort) // Из книгата "Теоретични 6 #{ // алгоритми на C++" от 7 # for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 # for (int j = i - 1; j >= 0; --j) 9 # if (toSort[j+1] < toSort[j]) 10 # swap(toSort[j], toSort[j+1]); 11 # else // Тези 2 реда ги няма в 12 # break; // горепосочената книга! 13 #} 14 15 # Нека индексът на външния цикъл (i) е r5, а на вътрешния (j) е r6. 16 17 .global inssort 18 inssort: 19 0000 38A00001 li r5,1 #for (int i = 1; 20 0004 7C052000 L1: cmpw r5,r4 # i < toSort.size(); 21 0008 4C800020 bgelr # Иначе край 22 000c 7CA62B78 mr r6,r5 # for (int j = i 23 0010 34C6FFFF L2: addic. r6,r6,-1# - 1; --j) 24 0014 41800028 blt L3 # j >= 0; 25 0018 54C9103A slwi r9,r6,2 # Превърни индекса в адресно отместване 26 001c 7D234A14 add r9,r3,r9# Получи адреса на toSort[j] 27 0020 80E90000 lwz r7,0(r9)# toSort[j] 28 0024 81090004 lwz r8,4(r9)# toSort[j+1] 29 0028 7C083800 cmpw r8,r7 # if (toSort[j+1] < toSort[j]) 30 002c 40800010 bge L3 31 0030 90E90004 stw r7,4(r9)# swap(toSort[j], toSort[j+1]; 32 0034 91090000 stw r8,0(r9) 33 0038 4BFFFFD8 b L2 # Край на вътрешния цикъл 34 003c 38A50001 L3: addi r5,r5,1 # else break; ++i) 35 0040 4BFFFFC4 b L1 # Край на външния цикъл SPARC GAS inssort.s page 1 1 ! Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 ! вмъкването масив от думи със знак с начален адрес в регистър %o0 и брой 3 ! елементи (поне 2) в регистър %o1. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 ! Нека индексът на външния цикъл (i) е %o2, а на вътрешния (j) е %o3. 16 17 .global inssort 18 inssort: 19 0000 94102001 mov 1,%o2 !for (unsigned i = 1; 20 0004 80A28009 L1: cmp %o2,%o1 21 0008 1A800010 bcc L4 ! i < toSort.size(); 22 000c 9610000A mov %o2,%o3 ! for (unsigned j = i 23 0010 96A2E001 L2: subcc %o3,1,%o3! - 1; --j) 24 0014 0A80000B bcs L3 ! j != -1; 25 0018 992AE002 sll %o3,2,%o4 ! Превърни индекса в адресно отместване 26 001c 9802000C add %o0,%o4,%o4! Получи адреса на toSort[j] 27 0020 DA030000 ld [%o4],%o5 ! „ldd“ изисква подравняване на 8! 28 0024 C2032004 ld [%o4+4],%g1 29 0028 80A0400D cmp %g1,%o5 ! if (toSort[j+1] < toSort[j]) 30 002c 16800005 bge L3 31 0030 01000000 nop 32 0034 DA232004 st %o5,[%o4+4]! swap(toSort[j], toSort[j+1]; 33 0038 10BFFFF6 ba L2 ! Край на вътрешния цикъл; изпълнява се след „st“! 34 003c C2230000 st %g1,[%o4] 35 0040 10BFFFF1 L3: ba L1 ! Край на външния цикъл; изпълнява се след „add“! 36 0044 9402A001 add %o2,1,%o2! else break; ++i) 37 0048 81C3E008 L4: retl 38 004c 01000000 nop MIPS GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър $4 и брой 3 # елементи (поне 2) в регистър $5. 4 5 #void insertionSort(vector& toSort) // Из книгата "Теоретични 6 #{ // алгоритми на C++" от 7 # for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 # for (int j = i - 1; j >= 0; --j) 9 # if (toSort[j+1] < toSort[j]) 10 # swap(toSort[j], toSort[j+1]); 11 # else // Тези 2 реда ги няма в 12 # break; // горепосочената книга! 13 #} 14 15 # Нека индексът на външния цикъл (i) е $6, а на вътрешния (j) е $7. 16 17 .ent inssort 18 .global inssort 19 inssort: 20 0000 24060001 LI $6,1 #for (int i = 1; 21 0004 00C5082A 10200011 00000000 L1: BGE $6,$5,L4# i < toSort.size(); 22 0010 00C03821 MOVE $7,$6 # for (int j = i 23 0014 24E7FFFF L2: ADDIU $7,$7,-1# - 1; --j) 24 0018 04E0000B 00000000 BLTZ $7,L3 # j >= 0; 25 0020 00075080 SLL $10,$7,2 # Превърни индекса в адресно отместване 26 0024 008A5021 ADDU $10,$4,$10# Получи адреса на toSort[j] 27 0028 8D480000 LW $8,0($10) # toSort[j] 28 002c 8D490004 LW $9,4($10) # toSort[j+1] 29 0030 0128082A 10200004 00000000 BGE $9,$8,L3 # if (toSort[j+1] < toSort[j]) 30 003c AD480004 SW $8,4($10) # swap(toSort[j], toSort[j+1]; 31 SW $9,0($10) 32 0040 1000FFF4 AD490000 B L2 # Край на вътрешния цикъл 33 L3: ADDIU $6,$6,1 # else break; ++i) 34 0048 1000FFEE 24C60001 B L1 # Край на външния цикъл 35 0050 03E00008 00000000 L4: JR $31 36 0058 00000000 00000000 .end inssort RISC-V GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър a0 и брой 3 # елементи (поне 2) в регистър a1. 4 5 #void insertionSort(vector& toSort) // Из книгата "Теоретични 6 #{ // алгоритми на C++" от 7 # for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 # for (int j = i - 1; j >= 0; --j) 9 # if (toSort[j+1] < toSort[j]) 10 # swap(toSort[j], toSort[j+1]); 11 # else // Тези 2 реда ги няма в 12 # break; // горепосочената книга! 13 #} 14 15 # Нека индексът на външния цикъл (i) е a2, а на вътрешния (j) е a3. 16 17 .global inssort 18 inssort: 19 0000 0546 LI a2,1 #for (int i = 1; 20 0002 6356B602 L1: BGE a2,a1,L4# i < toSort.size(); 21 0006 B286 MV a3,a2 # for (int j = i 22 0008 FD16 L2: ADDI a3,a3,-1# - 1; --j) 23 000a 63C00602 BLTZ a3,L3 # j >= 0; 24 000e 13982600 SLLI a6,a3,2 # Превърни индекса в адресно отместване 25 0012 2A98 ADD a6,a0,a6# Получи адреса на toSort[j] 26 0014 03270800 LW a4,0(a6)# toSort[j] 27 0018 83274800 LW a5,4(a6)# toSort[j+1] 28 001c 63D7E700 BGE a5,a4,L3# if (toSort[j+1] < toSort[j]) 29 0020 2322E800 SW a4,4(a6)# swap(toSort[j], toSort[j+1]); 30 0024 2320F800 SW a5,0(a6) 31 0028 C5B7 J L2 # Край на вътрешния цикъл 32 002a 0506 L3: ADDI a2,a2,1 # else break; ++i) 33 002c D9BF J L1 # Край на външния цикъл 34 002e 8280 L4: RET Nios II GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър r4 и брой 3 # елементи (поне 2) в регистър r5. 4 5 #void insertionSort(vector& toSort) // Из книгата "Теоретични 6 #{ // алгоритми на C++" от 7 # for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 # for (int j = i - 1; j >= 0; --j) 9 # if (toSort[j+1] < toSort[j]) 10 # swap(toSort[j], toSort[j+1]); 11 # else // Тези 2 реда ги няма в 12 # break; // горепосочената книга! 13 #} 14 15 # Нека индексът на външния цикъл (i) е r6, а на вътрешния (j) е r7. 16 17 .global inssort 18 inssort: 19 0000 54008001 MOVUI r6,1 #for (int i = 1; 20 0004 0E0D4031 L1: BGE r6,r5,L4# i < toSort.size(); 21 0008 3A880F30 MOV r7,r6 # for (int j = i 22 000c C4FFFF39 L2: SUBI r7,r7,1 # - 1; --j) 23 0010 16080038 BLT r7,r0,L3# j >= 0; 24 0014 BA901438 SLLI r10,r7,2 # Превърни индекса в адресно отместване 25 0018 3A889522 ADD r10,r4,r10# Получи адреса на toSort[j] 26 001c 17000052 LDW r8,(r10) # toSort[j] 27 0020 17014052 LDW r9,4(r10) # toSort[j+1] 28 0024 0E03004A BGE r9,r8,L3 # if (toSort[j+1] < toSort[j]) 29 0028 15010052 STW r8,4(r10) # swap(toSort[j], toSort[j+1]); 30 002c 15004052 STW r9,(r10) 31 0030 06F63F00 BR L2 # Край на вътрешния цикъл 32 0034 44008031 L3: ADDI r6,r6,1 # else break; ++i) 33 0038 06F23F00 BR L1 # Край на външния цикъл 34 003c 3A2800F8 L4: RET Xtensa GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър a2 и брой 3 # елементи (поне 2) в регистър a3. 4 5 #void insertionSort(vector& toSort) // Из книгата "Теоретични 6 #{ // алгоритми на C++" от 7 # for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 # for (int j = i - 1; j >= 0; --j) 9 # if (toSort[j+1] < toSort[j]) 10 # swap(toSort[j], toSort[j+1]); 11 # else // Тези 2 реда ги няма в 12 # break; // горепосочената книга! 13 #} 14 15 # Нека индексът на външния цикъл (i) е a4, а на вътрешния (j) е a5. 16 17 .global inssort 18 inssort: 19 0000 0C14 MOVI a4,1 #for (int i = 1; 20 0002 37A41C L1: BGE a4,a3,L4# i < toSort.size(); 21 0005 5D04 MOV a5,a4 # for (int j = i 22 0007 0B55 L2: ADDI a5,a5,-1# - 1; --j) 23 0009 960501 BLTZ a5,L3 # j >= 0; 24 000c 2085A0 ADDX4 a8,a5,a2# Получи адреса на toSort[j] 25 000f 6808 L32I a6,a8,0 # toSort[j] 26 0011 7818 L32I a7,a8,4 # toSort[j+1] 27 0013 67A706 BGE a7,a6,L3# if (toSort[j+1] < toSort[j]) 28 0016 6918 S32I a6,a8,4 # swap(toSort[j], toSort[j+1]); 29 0018 7908 S32I a7,a8,0 30 001a 46FAFF J L2 # Край на вътрешния цикъл 31 001d 1B44 L3: ADDI a4,a4,1 # else break; ++i) 32 001f C6F7FF J L1 # Край на външния цикъл 33 0022 0DF0 L4: RET 88K GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър r2 и брой 3 # елементи (поне 2) в регистър r3. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 # Нека индексите на външния (i) и вътрешния цикли (j) са регистри r4 и r5. 16 17 .global _inssort 18 0000 58800001 _inssort: 19 0004 F4C47C03 or r4,r0,1 #for (int i = 1; 20 0008 D966000E L1: cmp r6,r4,r3 21 000c F4A45800 bb1 hs,r6,L4# i < toSort.size(); 22 0010 64A50001 or r5,r4,r0# for (int j = i 23 0014 E9850009 L2: subu r5,r5,1 # - 1; --j) 24 0018 F4E21605 bcnd lt0,r5,L3# j >= 0; 25 001c 60C50001 ld r7,r2[r5] 26 0020 F5021606 addu r6,r5,1 # j+1 27 0024 F5287C07 ld r8,r2[r6] 28 0028 D8E90004 cmp r9,r8,r7 29 002c F4E22606 bb1 ge,r9,L3#_______ if (toSort[j+1] < toSort[j]) 30 0030 F5022605 st r7,r2[r6]# \ swap(toSort[j], toSort[j+1]); 31 0034 C3FFFFF7 st r8,r2[r5]# \______else break; 32 0038 60840001 br L2 # Край на вътрешния цикъл 33 003c C3FFFFF2 L3: addu r4,r4,1 # ++i) 34 0040 F400C001 br L1 # Край на външния цикъл L4: jmp r1 Or1k GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър R3 и брой 3 # елементи (поне 2) в регистър R4. 4 5 #void insertionSort(vector& toSort) // Из книгата "Теоретични 6 #{ // алгоритми на C++" от 7 # for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 # for (int j = i - 1; j >= 0; --j) 9 # if (toSort[j+1] < toSort[j]) 10 # swap(toSort[j], toSort[j+1]); 11 # else // Тези 2 реда ги няма в 12 # break; // горепосочената книга! 13 #} 14 .global inssort 15 16 # Нека индексът на външния цикъл (i) е R5, а на вътрешния (j) е R6. 17 18 inssort: 19 0000 A8A00001 L.ORI R5,R0,1 #for (unsigned i = 1; 20 0004 E4852000 L1: L.SFLTU R5,R4 21 0008 0C000011 L.BNF L4 # i < toSort.size(); 22 000c E0C50004 L.OR R6,R5,R0# for (unsigned j = i 23 0010 9CC6FFFF L2: L.ADDI R6,R6,-1# - 1; --j) 24 0014 BC06FFFF L.SFEQI R6,-1 # j != -1; 25 0018 1000000B L.BF L3 26 001c B8E60002 L.SLLI R7,R6,2 # Превърни индекса в адресно отместване 27 0020 E0E33800 L.ADD R7,R3,R7# Получи адреса на toSort[j] 28 0024 85070000 L.LWZ R8,0(R7) 29 0028 85670004 L.LWZ R11,4(R7) 30 002c E58B4000 L.SFLTS R11,R8 # if (toSort[j+1] < toSort[j]) 31 0030 0C000005 L.BNF L3 32 0034 15000000 L.NOP 0 33 0038 D4074004 L.SW 4(R7),R8# swap(toSort[j], toSort[j+1]); 34 003c 03FFFFF5 L.J L2 # Край на вътрешния цикъл; изпълнява се след „L.SW“! 35 0040 D4075800 L.SW 0(R7),R11 36 0044 03FFFFF0 L3: L.J L1 # Край на външния цикъл; изпълнява се след „L.ADDI“! 37 0048 9CA50001 L.ADDI R5,R5,1 # else break; ++i) 38 004c 44004800 L4: L.JR LR 39 0050 15000000 L.NOP 0 Xilinx MicroBlaze GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър R5 и брой 3 # елементи (поне 2) в регистър R6. 4 5 #void insertionSort(vector& toSort) // Из книгата "Теоретични 6 #{ // алгоритми на C++" от 7 # for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 # for (int j = i - 1; j >= 0; --j) 9 # if (toSort[j+1] < toSort[j]) 10 # swap(toSort[j], toSort[j+1]); 11 # else // Тези 2 реда ги няма в 12 # break; // горепосочената книга! 13 #} 14 15 # Нека индексът на външния цикъл (i) е R7, а на вътрешния (j) е R8. 16 17 .global inssort 18 inssort: 19 0000 0100E0A0 ORI R7,R0,1 #for (int i = 1; 20 0004 03382615 L1: CMPU R9,R6,R7# i < toSort.size(); 21 0008 3C00A9BC BGEI R9,L4 22 000c 00000781 OR R8,R7,R0# for (int j = i 23 0010 FFFF0821 L2: ADDI R8,R8,-1# - 1; --j) 24 0014 280048BC BLTI R8,L3 # j >= 0; 25 0018 02042865 BSLLI R9,R8,2 # Превърни индекса в адресно отместване 26 001c 00282901 ADD R9,R9,R5# Получи адреса на toSort[j] 27 0020 000069E8 LWI R3,R9,0 # toSort[j] 28 0024 040089E8 LWI R4,R9,4 # toSort[j+1] 29 0028 01204315 CMP R10,R3,R4# if (toSort[j+1] < toSort[j]) 30 002c 1000AABC BGEI R10,L3 31 0030 040069F8 SWI R3,R9,4 # swap(toSort[j], toSort[j+1]); 32 0034 000089F8 SWI R4,R9,0 33 0038 D8FF00B8 BRI L2 # Край на вътрешния цикъл 34 003c 0100E720 L3: ADDI R7,R7,1 # else break; ++i) 35 0040 C4FF00B8 BRI L1 # Край на външния цикъл 36 0044 08000FB6 L4: RTSD R15,8 37 0048 00000080 NOP HPPA GAS inssort.s page 1 1 ; Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 ; вмъкването масив от думи със знак с начален адрес в регистър %R26 и брой 3 ; елементи (поне 2) в регистър %R25. 4 5 ;void insertionSort(vector& toSort) // Из книгата "Теоретични 6 ;{ // алгоритми на C++" от 7 ; for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 ; for (int j = i - 1; j >= 0; --j) 9 ; if (toSort[j+1] < toSort[j]) 10 ; swap(toSort[j], toSort[j+1]); 11 ; else // Тези 2 реда ги няма в 12 ; break; // горепосочената книга! 13 ;} 14 15 ; Нека индексът на външния цикъл (i) е %R24, а на вътрешния (j) е %R23. 16 17 .text 18 .global inssort 19 inssort: 20 0000 34180002 LDI 1,%R24 ;for (int i = 1; 21 0004 8B384058 L1: COMBF,< %R24,%R25,L4; i < toSort.size(); 22 0008 08180257 COPY %R24,%R23 ; for (int j = i // Изпълнява се преди „COMBF“! 23 000c B6F707FF L2: ADDI -1,%R23,%R23; - 1; --j) 24 0010 8EE06030 COMIBF,<= 0,%R23,L3 ; j >= 0; 25 0014 0B570A94 SH2ADDL %R23,%R26,%R20;Адрес на toSort[j], изпълнява се преди „COMIBF“! 26 0018 0E801095 LDWS 0(%R20),%R21; toSort[j] 27 001c 0E881096 LDWS 4(%R20),%R22; toSort[j+1] 28 0020 8AB64012 COMBF,<,N %R22,%R21,L3;При пре- if (toSort[j+1] < toSort[j]) 29 0024 0E951288 STWS %R21,4(%R20);<-ход се анулира! swap(toSort[j], toSort[j+1]); 30 0028 E81F1FBD B L2 ; Край на вътрешния цикъл 31 002c 0E961280 STWS %R22,0(%R20); Изпълнява се преди „B“! 32 0030 AF021F9D L3: ADDIB,TR 1,%R24,L1 ; else break; ++i) 33 0034 08000240 NOP ;\_ Край на външния цикъл 34 0038 E840C002 L4: BV,N (%R2) 34 00000000 Renesas / SuperH SH GAS Little Endian inssort.s page 1 1 ! Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 ! вмъкването масив от думи със знак с начален адрес в регистър R4 и брой 3 ! елементи (поне 2) в регистър R5. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 ! Нека индексът на външния цикъл (i) е R2, а на вътрешния (j) е R3. 16 17 .global inssort 18 inssort: 19 0000 01E2 MOV #1,R2 !for (int i = 1; 20 0002 2361 MOV R2,R1 ! =1 21 0004 5232 L1: CMP/HS R5,R2 ! i < toSort.size(); 22 0006 0E89 BT L4 23 0008 2363 MOV R2,R3 ! for (int j = i 24 000a 1A33 L2: SUBC R1,R3 ! T=0 - 1; --j) 25 000c 0989 BT L3 ! j >= 0; 26 000e 3360 MOV R3,R0 27 0010 0840 SHLL2 R0 ! Превърни индекса в адресно отместване 28 0012 4C30 ADD R4,R0 ! Получи адреса на toSort[j] 29 0014 0266 MOV.L @R0,R6 ! toSort[j] 30 0016 0157 MOV.L @(4,R0),R7!toSort[j+1] 31 0018 6337 CMP/GE R6,R7 ! if (toSort[j+1] < toSort[j]) 32 001a 0289 BT L3 33 001c 6110 MOV.L R6,@(4,R0)! swap(toSort[j], toSort[j+1]); 34 001e 7220 MOV.L R7,@R0 35 0020 F38B BF L2 ! Край на вътрешния цикъл 36 0022 0172 L3: ADD #1,R2 ! else break; ++i) 37 0024 EE89 BT L1 ! Край на външния цикъл 38 0026 0B00 L4: RTS 39 0028 0900 NOP GAS for CRIS inssort.s page 1 1 ; Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 ; вмъкването масив от думи със знак с начален адрес в регистър R10 и брой 3 ; елементи (поне 2) в регистър R11. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 ; Нека индексът на външния цикъл (i) е R12, а на вътрешния (j) е R13. 16 17 .global inssort 18 inssort: 19 0000 88E2 SUBQ 8,$SP ; Съхрани R0–R1 (ETRAX FS Designer’s Reference, стр.212 20 0002 FE1B MOVEM $R1,[$SP] 21 0004 41C2 MOVEQ 1,$R12 ;for (unsigned i = 1; 22 0006 EBC6 L1: CMP.D $R11,$R12 23 0008 1E00 BHS L4 ; i < toSort.size(); 24 000a 6CD6 MOVE.D $R12,$R13; for (unsigned j = i 25 000c 81D2 L2: SUBQ 1,$R13 ; - 1; --j) 26 000e 1410 BLO L3 ; j != -1; 27 0010 6AD5 ADDI $R13.D,$R10,$ACR; Получи адреса на toSort[j] 28 0012 BF1B MOVEM [$ACR],$R1 29 0014 E016 CMP.D $R0,$R1 ; if (toSort[j+1] < toSort[j]) 30 0016 0CA0 BGE L3 31 0018 B017 XOR $R0,$R1 ; swap(toSort[j], toSort[j+1]); 32 001a B107 XOR $R1,$R0 33 001c B017 XOR $R0,$R1 34 001e EFE0 BA L2 ; Край на вътрешния цикъл; изпълнява се след „MOVEM“! 35 0020 FF1B MOVEM $R1,[$ACR] 36 0022 E5E0 L3: BA L1 ; Край на външния цикъл; изпълнява се след „ADDQ“! 37 0024 01C2 ADDQ 1,$R12 ; else break; ++i) 38 0026 F0B9 L4: RET 39 0028 BE1F0000 MOVEM [$SP+],$R1; Изпълнява се преди „RET“! BFIN GAS inssort.s page 1 1 # Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 # вмъкването масив от думи със знак с начален адрес в регистър R0 и брой 3 # елементи (поне 2) в регистър R1. 4 5 /* void insertionSort(vector& toSort)// Из книгата "Теоретични алгоритми 6 { // на C++" от Кевин де Кайзер (2015 г.) 7 for (int i = 1; i < toSort.size(); ++i) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 # Нека индексът на външния цикъл (i) е P1, а на вътрешния (j) е P2. 16 17 .global _inssort 18 _inssort: 19 0000 0968 P1 = 1; #for (unsigned i = 1; 20 0002 0132 L_1: P0 = R1; 21 0004 C109 CC = P1 < P0 (IU);# i < toSort.size(); 22 0006 1010 IF !CC JUMP L_4; 23 0008 5132 P2 = P1; # for (unsigned j = i 24 000a CA0D L_2: CC = P2 < 1 (IU);# - 1; --j) 25 000c FA6F P2 += -1; # j >= 0; 26 000e 0A18 IF CC JUMP L_3; 27 0010 0032 P0 = R0; # Получи адреса на 28 0012 105E P0 = P0 + (P2 << 2);# toSort[j] 29 0014 0291 R2 = [P0]; # toSort[j] 30 0016 43A0 R3 = [P0 + 4]; # toSort[j+1] 31 0018 9308 CC = R3 < R2; # if (toSort[j+1] < toSort[j]) 32 001a 0410 IF !CC JUMP L_3; 33 001c 42B0 [P0 + 4] = R2; # swap(toSort[j], toSort[j+1]); 34 001e 0393 [P0] = R3; 35 0020 F52F JUMP L_2; # Край на вътрешния цикъл 36 0022 096C L_3: P1 += 1; # else break; ++i) 37 0024 EF2F JUMP L_1; # Край на външния цикъл 38 0026 1000 L_4: RTS; Hexagon GAS inssort.s page 1 1 // Да се напише подпрограма, която да сортира във възходящ ред по метода на 2 // вмъкването масив от думи със знак с начален адрес в регистър R0 и брой 3 // елементи (поне 2) в регистър R1. 4 5 /* void insertionSort(vector& toSort) // Из книгата "Теоретични 6 { // алгоритми на C++" от 7 for (int i = 1; i < toSort.size(); ++i) // Кевин де Кайзер (2015 г.) 8 for (int j = i - 1; j >= 0; --j) 9 if (toSort[j+1] < toSort[j]) 10 swap(toSort[j], toSort[j+1]); 11 else // Тези 2 реда ги няма в 12 break; // горепосочената книга! 13 } */ 14 15 // Нека индексът на външния цикъл (i) е R2, а на вътрешния (j) е R3. 16 17 .global inssort 18 inssort: 19 0000 22C00078 R2 = #1 //for (int i = 1; 20 0004 00C241F2 L1: P0 = CMP.LT(R2,R1)// i < toSort.size(); 21 { IF (!P0) JUMPR LR//Върни управлението 22 0008 C53F2350 R3 = R2 } // for (int j = i 23 L2: { R3 = ADD(R3,#-1)// - 1; --j) 24 000c 0E40C361 E3FFE3BF IF (R3<=#0) JUMP:NT L3 }// j != -1; 25 0014 46C003C4 R6 = ADDASL(R0,R3,#2) 26 { R5 = MEMW(R6) 27 0018 64016500 R4 = MEMW(R6+#4) } 28 001c 00C445F2 P0 = CMP.LT(R4,R5)// if (toSort[j+1] < toSort[j]) 29 { IF (P0) MEMD(R6) = R5:4// swap(toSort[j], toSort[j+1]); 30 0020 F660DF5C 00C4C640 IF (P0) JUMP L2 }// Край на вътрешния цикъл 31 L3: { R2 = ADD(R2,#1)// else break; ++i) 32 0028 224002B0 EEFFFF59 JUMP L1 } // Край на външния цикъл S/390 GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от рег.3 (> 2) думи със знак, указани от рег.2 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 #/* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 #void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 #{ // най-големия възел в корена му 8 # int i, tmp; 9 # 10 # n--; // Премини към база 0 11 # for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 # i = 2 * k; // Ляв потомък 13 # if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 # i++; // левия и избери по-големия 15 # if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 # break; // на най-големия потомък, клонът е OK 17 # a[k] = a[i]; // Иначе потомъкът застава на мястото 18 # } // на родителя 19 # a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 #} // потомък, освен ако е по-голям от всички потомци 21 # 22 #void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 #{ // Сортиращо дърво, heap, tas: пирамида 24 # int i, tmp; 25 # 26 # for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 # downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 # for (i = n - 1; i > 0; i--) { 29 # tmp = a[i]; // Размени местата на максимума 30 # a[i] = a[0]; // и последния елемент на масива 31 # a[0] = tmp; 32 # downHeap(a, 0, i); // Препострой сортиращото дърво за 33 # } // неотсортираната част от масива 34 #} 35 #*/ 36 37 .global heapSort #void heapSort(int *a, int n) // 2, 3 38 heapSort: #{ int i, tmp; // 5 (3), 5 39 0000 9069F008 STM 6,9,8(15) #Съхрани използваните регистри (LNUX-1007-02) 40 0004 1799 XR 9,9 #Подготви нечетен регистър за BRXH 41 0006 1853 LR 5,3 # for (i = n 42 0008 88500001 SRL 5,1 # / 2; i >= 0; i--) 43 000c A73AFFFF AHI 3,-1 #n-- 44 0010 1845 L1: LR 4,5 #i 45 0012 A785001B BRAS 8,DownHeap # downHeap(a, i, n); // 2,4,3 46 0016 A75AFFFF AHI 5,-1 # // i--) 47 001a A7B4FFFB JNL L1 # // i >= 0; 48 001e 58602000 L2: L 6,0(2) #a[0] for (i = n - 1; i > 0; i--) { // 3 = i 49 0022 1813 LR 1,3 #i 50 0024 89100002 SLL 1,2 #4*i 51 0028 58521000 L 5,0(2,1) # tmp = a[i]; 52 002c 50621000 ST 6,0(2,1) # a[i] = a[0]; 53 0030 50502000 ST 5,0(2) # a[0] = tmp; 54 0034 1744 XR 4,4 #k = 0 55 0036 A73AFFFF AHI 3,-1 #i-- (n--) 56 003a A7850007 BRAS 8,DownHeap # downHeap(a, 0, i); // 2,4,3 57 003e 8439FFF0 BRXH 3,9,L2 # } // i > 0 58 0042 9869F008 LM 6,9,8(15) #Възстанови съхранените регистри 59 0046 07FE BR 14 #} 60 0048 1814 DownHeap: LR 1,4 #k 61 004a 89100002 SLL 1,2 #4*k void downHeap(int *a, int k, int n)// 2,4,3 62 004e 58721000 L 7,0(2,1)#tmp=a[k]{ 63 0052 1813 L3: LR 1,3 #n int i,tmp;/* 6,7 */n--;//вече намалено 64 0054 88100001 SRL 1,1 #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 65 0058 1541 CLR 4,1 #k <= n / 2? 66 005a A7240023 JH L5 #ако не, край на цикъла 67 005e 1864 LR 6,4 #k 68 0060 89600001 SLL 6,1 # i = 2 * k; 69 0064 1816 LR 1,6 #i 70 0066 89100002 SLL 1,2 #4*i 71 006a 1563 CLR 6,3 # if (i < n 72 006c A7B4000A JNL L4 # && 73 0070 58021000 L 0,0(2,1) #a[i] 74 0074 59021004 C 0,4(2,1) # a[i] < a[i+1]) 75 0078 A7B40004 JNL L4 76 007c A76A0001 AHI 6,1 # i++; 77 0080 1816 L4: LR 1,6 #i 78 0082 89100002 SLL 1,2 #4*i 79 0086 58021000 L 0,0(2,1) #a[i] 80 008a 1970 CR 7,0 # if (tmp >= a[i]) 81 008c A7B4000A JNL L5 # break; 82 0090 1814 LR 1,4 #k 83 0092 89100002 SLL 1,2 #4*k 84 0096 50021000 ST 0,0(2,1) # a[k] = a[i]; 85 009a 1846 LR 4,6 # } // k = i 86 009c A7F4FFDB J L3 87 00a0 1814 L5: LR 1,4 #k 88 00a2 89100002 SLL 1,2 #4*k 89 00a6 50721000 ST 7,0(2,1) # a[k] = tmp; 90 00aa 07F8 BR 8 #} ==> id32/heapSort.s <== 1 * Sort in ascending order an array of 7(4) (>2) signed words pointed to by 7(0) 2 * Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 * average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 * Heap - a binary tree in which the parent is not lesser than its children. 6 *void downHeap(int *a, int k, int n) // Examine the sub-tree and move the 7 *{ // greatest node to its root 8 * int i, tmp; 9 * 10 * n--; // Switch to base 0 11 * for (tmp = a[k]; k <= n / 2; k = i) { // Save the parent in the root 12 * i = 2 * k; // Left child 13 * if (i < n && a[i] < a[i+1]) // Right child? Compare it to 14 * i++; // the left one & choose the larger one 15 * if (tmp >= a[i]) // If the parent's larger than or equal 16 * break; // to the largest child the branch's OK 17 * a[k] = a[i]; // Else the child takes its parent's 18 * } // place 19 * a[k] = tmp; // Finally the parent swaps its place with the largest 20 *} // child unless it's bigger than all the children 21 * 22 *void heapSort(int *a, int n) // Heap (pyramidal) sort (tri par tas) 23 *{ // Sorting tree, heap, tas: a pyramid 24 * int i, tmp; 25 * 26 * for (i = n / 2; i >= 0; i--) // Create a sorting tree (largest mem- 27 * downHeap(a, i, n); // ber of the array will be at its root 28 * for (i = n - 1; i > 0; i--) { 29 * tmp = a[i]; // Swap the maximal and the last 30 * a[i] = a[0]; // members of the array 31 * a[0] = tmp; 32 * downHeap(a, 0, i); // Rebuild the sorting tree for the 33 * } // non-sorted part of the array 34 *} 35 36 entry heapSort void heapSort(int *a, int n) // 2, 3 00000000d 37 heapSort equ * { int i, tmp; // 5 (3), 5 00000d 5827 0000 38 l 2,0(7) a 00004d 5837 0004 39 l 3,4(7) n 00008d CB70 0020 40 shi 7,32(0) Allocate stack space (8 * 4 bytes = 32 bytes) 0000Cd D087 0000 41 stm 8,0(7) Save reg. 8-15 (used by the calling function) 00010d 0853 42 lr 5,3 for (i = n 00012d 1051 43 srls 5,1 / 2; i >= 0; i--) 00014d 2731 44 sis 3,1 n-- 00016d 0845 45 L1 lr 4,5 i 00018d 4180 8036 00000052d 46 bal 8,DownHeap downHeap(a, i, n); // 2,4,3 0001Cd 2751 47 sis 5,1 // i--) 0001Ed 2284 00000016d 48 bnls L1 // i >= 0; 00020d 5862 0000 49 L2 l 6,0(2) a[0] for (i = n - 1; i > 0; i--) { // 3 = i 00024d 0813 50 lr 1,3 i 00026d 1112 51 slls 1,2 4*i 00028d 5852 4100 0000 52 l 5,0(2,1) tmp = a[i]; 0002Ed 5062 4100 0000 53 st 6,0(2,1) a[i] = a[0]; 00034d 5052 0000 54 st 5,0(2) a[0] = tmp; 00038d 0744 55 xr 4,4 k = 0 0003Ad 2731 56 sis 3,1 i-- (n--) 0003Cd 4180 8012 00000052d 57 bal 8,DownHeap downHeap(a, 0, i); // 2,4,3 00040d C530 0000 58 cli 3,0(0) // i > 0 00044d 4230 FFD8 00000020d 59 bnz L2(0) } 00048d D187 0000 60 lm 8,0(7) Restore the saved registers 8-15 0004Cd CA70 0020 61 ahi 7,32(0) Deallocate the stack space 00050d 030F 62 br 15 } 00052d 0814 63 DownHeap lr 1,4 k 00054d 1112 64 slls 1,2 4*k void downHeap(int *a, int k, int n)// 2,4,3 00056d 5892 4100 0000 65 l 9,0(2,1) tmp=a[k]{ // already 0005Cd 0813 66 L3 lr 1,3 n int i,tmp;/* 6,9 */n--; // decremented 0005Ed 1011 67 srls 1,1 n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 00060d 0941 68 cr 4,1 k <= n / 2? 00062d 4220 803A 000000A0d 69 bp L5(0) if not, end of loop 00066d 0864 70 lr 6,4 k 00068d 1161 71 slls 6,1 i = 2 * k; 0006Ad 0816 72 lr 1,6 i 0006Cd 1112 73 slls 1,2 4*i 0006Ed 0563 74 clr 6,3 if (i < n 00070d 2389 00000082d 75 bnls L4 && 00072d 5802 4100 0000 76 l 0,0(2,1) a[i] 00078d 5902 4100 0004 77 c 0,4(2,1) a[i] < a[i+1]) 0007Ed 2312 00000082d 78 bnms L4 00080d 2661 79 ais 6,1 i++; 00082d 0816 80 L4 lr 1,6 i 00084d 1112 81 slls 1,2 4*i 00086d 5802 4100 0000 82 l 0,0(2,1) a[i] 0008Cd 0990 83 cr 9,0 if (tmp >= a[i]) 0008Ed 2319 000000A0d 84 bnms L5 break; 00090d 0814 85 lr 1,4 k 00092d 1112 86 slls 1,2 4*k 00094d 5002 4100 0000 87 st 0,0(2,1) a[k] = a[i]; 0009Ad 0846 88 lr 4,6 } // k = i 0009Cd 4300 FFBC 0000005Cd 89 b L3(0) 000A0d 0814 90 L5 lr 1,4 k 000A2d 1112 91 slls 1,2 4*k 000A4d 5092 4100 0000 92 st 9,0(2,1) a[k] = tmp; 000AAd 0308 93 br 8 } VAX GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от R1 (R1 > 2) думи със знак, указани от R0 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global _heapSort # void heapSort(int *a, int n) // 4(AP), 8(AP) 38 _heapSort: # { // (R0, R1) 39 0000 7C00 .word 0x7C # R2-6 | int i, tmp; // R3 (R1), R3 40 0002 7DAC0450 MOVQ 4(AP),R0 # R0-1 | 41 0006 788FFF51 53 ASHL $-1,R1,R3 # | for (i = n / 2; i >= 0; i--) 42 000b D751 DECL R1 # n-- | 43 000d D05352 L1: MOVL R3,R2 # i | 44 0010 1019 BSBB DOWNHEAP # | downHeap(a, i, n); //R0,R2,R1 45 0012 F453F8 SOBGEQ R3,L1 # | // i >= 0; i--) 46 0015 D06053 L2: MOVL (R0),R3 # | for (i = n - 1; i > 0; i--) {//R1 = i 47 0018 D0416060 MOVL (R0)[R1],(R0) # | tmp = a[i]; 48 001c D0534160 MOVL R3,(R0)[R1] # | a[i] = a[0]; 49 0020 D452 CLRL R2 # k = 0 | a[0] = tmp; 50 0022 D751 DECL R1 # i-- (n--) | downHeap(a, 0, i); //R0,R2,R1 51 0024 1005 BSBB DOWNHEAP # | } 52 0026 D551 TSTL R1 # } // i > 0; 53 0028 12EB BNEQ L2 54 002a 04 RET # void downHeap(int *a, int k, int n)//R0,R2,R1 55 002b D0426055 DOWNHEAP: MOVL (R0)[R2],R5 # { | int i,tmp;/*R4,5*/n--;//вече намалено 56 002f 788FFF51 56 L3: ASHL $-1,R1,R6 # | for (tmp = a[k]; k <= n / 2; k = i) { 57 0034 D15256 CMPL R2,R6 # k <= n / 2 ? | 58 0037 1A26 BGTRU L5 # ако не, край на цикъла 59 0039 78015254 ASHL $1,R2,R4 # | i = 2 * k; 60 003d F1540051 0B00 ACBL R4,$0,R1,L4#i и n < 2^31| if (i < n && 61 0043 F1446000 44A00402 00 ACBL (R0)[R4],$0,4(R0)[R4],L4# a[i] < a[i+1]) 62 004c D654 INCL R4 # | i++; 63 004e F1550044 600A00 L4: ACBL R5,$0,(R0)[R4],L5# | if (tmp >= a[i]) break; 64 0055 D0446042 60 MOVL (R0)[R4],(R0)[R2]# | a[k] = a[i]; 65 005a D05452 MOVL R4,R2 # k = i | } 66 005d 11D0 BRB L3 # | 67 005f D0554260 L5: MOVL R5,(R0)[R2] # | a[k] = tmp; 68 0063 05 RSB # } ==> we32k/heapSort.s <== # Sort in ascending order an array of r1 (r1 > 2) signed words pointed to by r0 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 # Heap - a binary tree in which the parent is not lesser than its children. #void downHeap(int *a, int k, int n) // Examine the sub-tree and move the #{ // greatest node to its root # int i, tmp; # # n--; // Switch to base 0 # for (tmp = a[k]; k <= n / 2; k = i) { // Save the parent in the root # i = 2 * k; // Left child # if (i < n && a[i] < a[i+1]) // Right child? Compare it to # i++; // the left one & choose the larger one # if (tmp >= a[i]) // If the parent's larger than or equal # break; // to the largest child the branch's OK # a[k] = a[i]; // Else the child takes its parent's # } // place # a[k] = tmp; // Finally the parent swaps its place with the largest #} // child unless it's bigger than all the children # #void heapSort(int *a, int n) // Heap (pyramidal) sort (tri par tas) #{ // Sorting tree, heap, tas: a pyramid # int i, tmp; # # for (i = n / 2; i >= 0; i--) // Create a sorting tree (largest mem- # downHeap(a, i, n); // ber of the array will be at its root # for (i = n - 1; i > 0; i--) { # tmp = a[i]; // Swap the maximal and the last # a[i] = a[0]; // members of the array # a[0] = tmp; # downHeap(a, 0, i); // Rebuild the sorting tree for the # } // non-sorted part of the array #} section .text .globl heapSort #void heapSort(int *a, int n) // 0(ap), 4(ap) heapSort() heapSort: #{ // (r0, r1) 0: 10 43 SAVE %r3 # r3-8 int i, tmp; // r3 (r1), r3 2: 84 5a 40 MOVW 0(%ap),%r0 # 5: 84 74 41 MOVW 4(%ap),%r1 # 8: d4 01 41 43 LRSW3 &1,%r1,%r3 # for (i = n / 2; i >= 0; i--) c: 94 41 DECW %r1 # n-- e: 84 43 42 L1: MOVW %r3,%r2 # i 11: 37 35 BSBB DOWNHEAP # downHeap(a, i, n); //r0, r2, r1 13: bc 01 43 SUBW2 &1,%r3 # // i >= 0; i--) 16: 53 f8 BGEUB L1 18: 84 50 43 L2: MOVW (%r0),%r3 # for (i = n - 1; i > 0; i--) {//r1 = i 1b: d0 02 41 46 LLSW3 &2,%r1,%r6 1f: 9c 40 46 ADDW2 %r0,%r6 # &a[i] 22: 84 56 50 MOVW (%r6),(%r0) # tmp = a[i]; 25: 70 NOP 26: 84 43 56 MOVW %r3,(%r6) # a[i] = a[0]; 29: 70 NOP 2a: 80 42 CLRW %r2 # k = 0 a[0] = tmp; 2c: 94 41 DECW %r1 # i-- (n--) downHeap(a, 0, i); //r0, r2, r1 2e: 37 18 BSBB DOWNHEAP # } 30: 28 41 TSTW %r1 # // i > 0; 32: 77 e6 BNEB L2 34: 04 59 4c MOVAW (%fp),%sp RESTORE %r3 #} 37: 20 48 POPW %r8 39: 20 47 POPW %r7 3b: 20 46 POPW %r6 3d: 20 45 POPW %r5 3f: 20 44 POPW %r4 41: 20 43 POPW %r3 43: 20 49 POPW %fp 45: 08 RET 46: d0 02 42 46 DOWNHEAP: LLSW3 &2,%r2,%r6 #void downHeap(int *a, int k, int n)//r0,r2, r1 4a: 9c 40 46 ADDW2 %r0,%r6 # &a[k] { int i,tmp;/*r4,5*/n--;//already decrem. 4d: 84 56 45 MOVW (%r6),%r5 # for (tmp = a[k]; k <= n / 2; k = i) { 50: d4 01 41 46 L3: LRSW3 &1,%r1,%r6 54: 3c 46 42 CMPW %r6,%r2 # k <= n / 2 ? 57: 57 36 BGUB L5 # if not, end the loop 59: d0 01 42 44 LLSW3 &1,%r2,%r4 # i = 2 * k; 5d: 3c 41 44 CMPW %r1,%r4 # if (i < n && 60: 53 11 BGEUB L4 62: d0 02 44 46 LLSW3 &2,%r4,%r6 66: 9c 40 46 ADDW2 %r0,%r6 # &a[i] 69: 3c c6 04 56 CMPW 4(%r6),(%r6) # a[i] < a[i+1]) 6d: 43 04 BGEB L4 6f: 90 44 INCW %r4 # i++; 71: d0 02 44 46 L4: LLSW3 &2,%r4,%r6 75: 9c 40 46 ADDW2 %r0,%r6 # &a[i] 78: 3c 56 45 CMPW (%r6),%r5 # if (tmp >= a[i]) 7b: 43 12 BGEB L5 # break; 7d: d0 02 42 47 LLSW3 &2,%r2,%r7 81: 9c 40 47 ADDW2 %r0,%r7 # &a[k] 84: 84 56 57 MOVW (%r6),(%r7) # a[k] = a[i]; 87: 70 NOP 88: 84 44 42 MOVW %r4,%r2 # } // k = i 8b: 7b c5 BRB L3 8d: d0 02 42 47 L5: LLSW3 &2,%r2,%r7 91: 9c 40 47 ADDW2 %r0,%r7 # &a[k] 94: 84 45 57 MOVW %r5,(%r7) # a[k] = tmp; 97: 70 NOP 98: 78 RSB #} 99: 70 NOP 9a: 70 NOP 9b: 70 NOP 68K GAS heapSort.s page 1 1 | Подреди във възходящ ред масив от D1 (D1 > 2) думи със знак, указани от A0 2 | Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 | average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort 38 heapSort: | void heapSort(int *a, int n) // 4(SP), 8(SP) 39 0000 4CEF 0102 0004 MOVEML 4(%SP),%D1/%A0 | { // (A0, D1) 40 0006 C388 EXG %D1,%A0 41 0008 48E7 3C00 MOVEML %D2-%D5,-(%SP) | int i, tmp; // D3 (D1), D3 42 000c E9C1 301F BFEXTU %D1{0:31},%D3 | for (i = n / 2; i >= 0; i--) 43 0010 5381 SUBQL #1,%D1 | n-- | 44 0012 2403 L1: MOVEL %D3,%D2 | i | 45 0014 6122 BSRB DOWNHEAP | downHeap(a, i, n); //A0,D2,D1 46 0016 51CB FFFA DBF %D3,L1 | // i >= 0; i--) 47 001a 2610 L2: MOVEL (%A0),%D3 | for (i = n - 1; i > 0; i--) {//D1 = i 48 001c 20B0 1C00 MOVEL (%A0,%D1*4),(%A0) | tmp = a[i]; 49 0020 2183 1C00 MOVEL %D3,(%A0,%D1*4) | a[i] = a[0]; 50 0024 4282 CLRL %D2 | k = 0 | a[0] = tmp; 51 0026 5381 SUBQL #1,%D1 | i-- (n--) | downHeap(a, 0, i); //A0,D2,D1 52 0028 610E BSRB DOWNHEAP | } 53 002a 0C81 0000 0000 CMPIL #0,%D1 | } // i > 0; 54 0030 66E8 BNEB L2 55 0032 4CDF 003C MOVEML (%SP)+,%D2-%D5 56 0036 4E75 RTS | void downHeap(int *a, int k, int n)//A0,D2,D1 57 0038 2A30 2C00 DOWNHEAP: MOVEL (%A0,%D2*4),%D5 | { | int i,tmp;/*D4,5*/n--;//вече намалено 58 003c E9C1 001F L3: BFEXTU %D1{0:31},%D0 | for (tmp = a[k]; k <= n / 2; k = i) { 59 0040 B480 CMPL %D0,%D2 | k <= n / 2 ? | 60 0042 6224 BHIB L5 | ако не, край на цикъла 61 0044 2802 MOVEL %D2,%D4 | i = k 62 0046 D884 ADDL %D4,%D4 | * 2; 63 0048 B881 CMPL %D1,%D4 | if (i < n 64 004a 640C BHSB L4 | && 65 004c 2030 4C00 MOVEL (%A0,%D4*4),%D0 | a[i] 66 0050 B0B0 4C04 CMPL (4,%A0,%D4*4),%D0 | < a[i+1]) 67 0054 6C02 BGEB L4 68 0056 5284 ADDQL #1,%D4 | i++; 69 0058 BAB0 4C00 L4: CMPL (%A0,%D4*4),%D5 | if (tmp >= a[i]) 70 005c 6C0A BGEB L5 | break; 71 005e 21B0 4C00 2C00 MOVEL (%A0,%D4*4),(%A0,%D2*4) | a[k] = a[i]; 72 0064 2404 MOVEL %D4,%D2 | k = i | } 73 0066 60D4 BRAB L3 | 74 0068 2185 2C00 L5: MOVEL %D5,(%A0,%D2*4) | a[k] = tmp; 75 006c 4E75 RTS | } x86 NASM heapSort.s 1 ; Подреди във възходящ ред масив от EDX (EDX > 2) думи със знак, указан от EAX 2 ; Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 ; average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 ;/* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 ;void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 ;{ // най-големия възел в корена му 8 ; int i, tmp; 9 ; 10 ; n--; // Премини към база 0 11 ; for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 ; i = 2 * k; // Ляв потомък 13 ; if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 ; i++; // левия и избери по-големия 15 ; if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 ; break; // на най-големия потомък, клонът е OK 17 ; a[k] = a[i]; // Иначе потомъкът застава на мястото 18 ; } // на родителя 19 ; a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 ;} // потомък, освен ако е по-голям от всички потомци 21 ; 22 ;void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 ;{ // Сортиращо дърво, heap, tas: пирамида 24 ; int i, tmp; 25 ; 26 ; for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 ; downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 ; for (i = n - 1; i > 0; i--) { 29 ; tmp = a[i]; // Размени местата на максимума 30 ; a[i] = a[0]; // и последния елемент на масива 31 ; a[0] = tmp; 32 ; downHeap(a, 0, i); // Препострой сортиращото дърво за 33 ; } // неотсортираната част от масива 34 ;} 35 ;*/ 36 37 section .text 38 global heapSort,_heapSort; в GCC декларирай с __attribute__((regparm(3))) 39 heapSort: 40 _heapSort: ; void heapSort(int *a, int n) 41 00000000 60 PUSHAD ; Използват се всички регистри 42 00000001 89D7 MOV EDI,EDX ; i = n { int i, tmp; // EDI (EDX), ECX 43 00000003 D1EF SHR EDI,1 ; i = n / 2 for (i = n / 2; i >= 0; i--) 44 00000005 4A DEC EDX ; n-- 45 00000006 89FD L1: MOV EBP,EDI ; i 46 00000008 E819000000 CALL DOWNHEAP; арг.: EAX, EBP, EDX downHeap(a, i, n); 47 0000000D 4F DEC EDI ; i-- 48 0000000E 79F6 JNS L1 ; ако i >= 0, продължи 49 00000010 31ED L2: XOR EBP,EBP ; k = 0 for (i = n - 1; i > 0; i--) { 50 00000012 8B0C90 MOV ECX,[EAX+4*EDX]; tmp = a[i]; 51 00000015 8708 XCHG ECX,[EAX];_________ _____ a[i] = a[0]; 52 00000017 890C90 MOV [EAX+4*EDX],ECX;___X_____ a[0] = tmp; 53 0000001A 4A DEC EDX ; i-- (n--) 54 0000001B E806000000 CALL DOWNHEAP; арг.: EAX, EDI, EDX downHeap(a, 0, i); 55 00000020 85D2 TEST EDX,EDX 56 00000022 75EC JNZ L2 ; } 57 00000024 61 POPAD ; } 58 00000025 C3 RET ; void downHeap(int*a,int k,int n)//EAX,EBP,EDX 59 00000026 8B0CA8 DOWNHEAP: MOV ECX,[EAX+4*EBP]; { int i,tmp;/*ESI,ECX*/n--;вече умалено 60 00000029 89D3 L3: MOV EBX,EDX ; n for (tmp = a[k]; k <= n / 2; k = i) { 61 0000002B D1EB SHR EBX,1 ; n / 2 62 0000002D 39DD CMP EBP,EBX ; k <= n / 2 ? 63 0000002F 7720 JA L5 ; ако не, край на цикъла 64 00000031 8D742D00 LEA ESI,[2*EBP]; i = 2 * k; 65 00000035 39D6 CMP ESI,EDX ; i < n ? if (i < n 66 00000037 730A JAE L4 ; ако не, прескочи && 67 00000039 8B1CB0 MOV EBX,[EAX+4*ESI]; a[i] < a[i+1]) 68 0000003C 3B5CB004 CMP EBX,[EAX+4*ESI+4] 69 00000040 7D01 JGE L4 70 00000042 46 INC ESI ; i++; 71 00000043 8B1CB0 L4: MOV EBX,[EAX+4*ESI]; if (tmp >= a[i]) 72 00000046 39D9 CMP ECX,EBX 73 00000048 7D07 JGE L5 ; break; 74 0000004A 891CA8 MOV [EAX+4*EBP],EBX; a[k] = a[i]; 75 0000004D 89F5 MOV EBP,ESI ; k = i } 76 0000004F EBD8 JMP L3 77 00000051 890CA8 L5: MOV [EAX+4*EBP],ECX; a[k] = tmp; 78 00000054 C3 RET ; } ARM GAS heapSort.s page 1 1 // Подреди във възходящ ред масив от R1 (R1 > 2) думи със знак, указани от R0 2 // Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 // average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort //void heapSort(int *a, int n) //R0, R1 38 heapSort: // { | int i, tmp; // R3 (R1), R3 39 0000 F0402DE9 STMFD SP!,{R4-R7,LR}//Съхрани използваните регистри (ARM IHI 0042F) 40 0004 A130A0E1 MOV R3,R1,LSR #1 // | for (i = n / 2; i >= 0; i--) 41 0008 011041E2 SUB R1,R1,#1 //n-- | 42 000c 0320A0E1 L1: MOV R2,R3 // i | 43 0010 0B0000EB BL DOWNHEAP // | downHeap(a, i, n); //R0,R2,R1 44 0014 013053E2 SUBS R3,R3,#1 // | // i--) 45 0018 FBFFFF2A BHS L1 // | // i >= 0; 46 001c 004090E5 L2: LDR R4,[R0] // | for (i = n - 1; i > 0; i--) {//R1 = i 47 0020 013190E7 LDR R3,[R0,R1,LSL #2]// | tmp = a[i]; 48 0024 014180E7 STR R4,[R0,R1,LSL #2]// | a[i] = a[0]; 49 0028 003080E5 STR R3,[R0] // | a[0] = tmp; 50 002c 0020A0E3 MOV R2,#0 // k = 0 | 51 0030 011041E2 SUB R1,R1,#1// i-- (n--) | downHeap(a, 0, i); //R0,R2,R1 52 0034 020000EB BL DOWNHEAP// | } 53 0038 000051E3 CMP R1,#0 // __} // i > 0; 54 003c F6FFFF1A BNE L2 // / void downHeap(int *a, int k, int n)//R0,R2,R1 55 0040 F080BDE8 LDMFD SP!,{R4-R7,PC}// /{ | int i,tmp;/*R4,5*/n--;//вече намалено 56 0044 025190E7 DOWNHEAP: LDR R5,[R0,R2,LSL #2]// | for (tmp = a[k]; k <= n / 2; k = i) { 57 0048 A10052E1 L3: CMP R2,R1,LSR #1//k <= n / 2 ? 58 004c 0C00008A BHI L5 // ако не, край на цикъла 59 0050 8240A0E1 MOV R4,R2,LSL #1// | i = 2 * k; 60 0054 010054E1 CMP R4,R1 // | if (i < n 61 0058 0300002A BHS L4 // | 62 005c 046180E0 ADD R6,R0,R4,LSL #2// | && 63 0060 C00096E8 LDMIA R6,{R6,R7}// | 64 0064 070056E1 CMP R6,R7 // | a[i] < a[i+1]) 65 0068 014084B2 ADDLT R4,R4,#1// | i++; 66 006c 046190E7 L4: LDR R6,[R0,R4,LSL #2]// | 67 0070 060055E1 CMP R5,R6 // | if (tmp >= a[i]) 68 0074 020000AA BGE L5 // | break; 69 0078 026180E7 STR R6,[R0,R2,LSL #2]// | a[k] = a[i]; 70 007c 0420A0E1 MOV R2,R4 // k = i | } 71 0080 F0FFFFEA B L3 72 0084 025180E7 L5: STR R5,[R0,R2,LSL #2]// | a[k] = tmp; 73 0088 1EFF2FE1 BX LR // } ARC GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от r1 (r1 > 2) думи със знак, указани от r0 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) # Прегледай поддървото и премести 7 { # най-големия възел в корена му 8 int i, tmp; 9 10 n--; # Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { # В корена запомни родителя 12 i = 2 * k; # Ляв потомък 13 if (i < n && a[i] < a[i+1]) # Ако има десен, сравни го с 14 i++; # левия и избери по-големия 15 if (tmp >= a[i]) # Ако родителят е по-голям или равен 16 break; # на най-големия потомък, клонът е OK 17 a[k] = a[i]; # Иначе потомъкът застава на мястото 18 } # на родителя 19 a[k] = tmp; # Накрая родителят си разменя мястото с най-големия 20 } # потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) # Пирамидално сортиране (tri par tas) 23 { # Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) # Създай сортиращо дърво (максималният 27 downHeap(a, i, n); # елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; # Размени местата на максимума 30 a[i] = a[0]; # и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); # Препострой сортиращото дърво за 33 } # неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort #void heapSort(int *a, int n) //r0, r1 38 heapSort: # { | int i, tmp; // r3 (r1), r3 39 0000 EB41 MOV_S r9,blink #Съхрани blink, защото BL_S ще го промени! 40 0002 2F23 4200 LSR r3,r1 # | for (i = n / 2; i >= 0; i--) 41 0006 2969 SUB_S r1,r1,1 #n-- | 42 0008 6042 L1: MOV_S r2,r3 # i | 43 000a 0BF8 BL_S DOWNHEAP # | downHeap(a, i, n); //r0,r2,r1 44 000c 4223 4380 SUB.F r3,r3,1 # | // i--) 45 0010 7CF7 BHS_S L1 # | // i >= 0; 46 0012 0010 0400 L2: LD r4,[r0] # a[0] | for (i = n - 1; i > 0; i--) {//r1 = i 47 0016 1520 4700 ADD2 r7,r0,r1# a + 4i | 48 001a 0017 0300 LD r3,[r7] # | tmp = a[i]; 49 001e 001F 0001 ST r4,[r7] # | a[i] = a[0]; 50 0022 0018 C000 ST r3,[r0] # | a[0] = tmp; 51 0026 4C70 MOV_S r2,0 # k = 0 | 52 0028 2969 SUB_S r1,r1,1 # i-- (n--) | downHeap(a, 0, i); //r0,r2,r1 53 002a 03F8 BL_S DOWNHEAP# __________| } // i > 0; 54 002c E709 1180 BRNE r1,0,L2 #____/ }void downHeap(int *a, int k, int n)//r0,r2,r1 55 0030 2020 4002 J [r9] # { | int i,tmp;/*r4,5*/n--;//вече намалено 56 0034 F020 8500 DOWNHEAP: LD.AS r5,[r0,r2]# | for (tmp = a[k]; k <= n / 2; k = i) { 57 0038 1520 8800 L3: ADD2 r8,r0,r2# a + 4k | 58 003c 2F27 4200 LSR r7,r1 # n / 2 | 59 0040 290F 8400 BRHI r2,r7,L5# k <= n / 2 ? ако не, край на цикъла 60 0044 2F24 8000 ASL r4,r2 # | i = 2 * k; 61 0048 110C 4500 BRHS r4,r1,L4# | if (i < n 62 004c F620 0601 LDD.AS r6,[r0,r4]# | && 63 0050 0C26 C081 CMP r6,r7 # | a[i] < a[i+1]) 64 0054 C024 6B00 ADD.LT r4,r4,1 # | i++; 65 0058 F020 0601 L4: LD.AS r6,[r0,r4]#a[i] | 66 005c 0D0D 8301 BRGE r5,r6,L5# | if (tmp >= a[i]) break; 67 0060 0018 8011 ST r6,[r8] # | a[k] = a[i]; 68 0064 8042 MOV_S r2,r4 # k = i | } 69 0066 EAF1 B_S L3 70 0068 0018 4011 L5: ST r5,[r8] # | a[k] = tmp; 71 006c E07E J_S [blink] # } PPC GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от r4 (r4 > 2) думи със знак, указани от r3 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 #/* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 #void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 #{ // най-големия възел в корена му 8 # int i, tmp; 9 # 10 # n--; // Премини към база 0 11 # for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 # i = 2 * k; // Ляв потомък 13 # if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 # i++; // левия и избери по-големия 15 # if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 # break; // на най-големия потомък, клонът е OK 17 # a[k] = a[i]; // Иначе потомъкът застава на мястото 18 # } // на родителя 19 # a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 #} // потомък, освен ако е по-голям от всички потомци 21 # 22 #void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 #{ // Сортиращо дърво, heap, tas: пирамида 24 # int i, tmp; 25 # 26 # for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 # downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 # for (i = n - 1; i > 0; i--) { 29 # tmp = a[i]; // Размени местата на максимума 30 # a[i] = a[0]; // и последния елемент на масива 31 # a[0] = tmp; 32 # downHeap(a, 0, i); // Препострой сортиращото дърво за 33 # } // неотсортираната част от масива 34 #} 35 #*/ 36 37 .global heapSort #void heapSort(int *a, int n) // r3, r4 38 heapSort: #{ int i, tmp; // r6 (r4), r6 39 0000 7C0802A6 mflr r0 #Съхрани lr, защото bl ще го промени! 40 0004 5486F87E srwi r6,r4,1 # for (i = n / 2; i >= 0; i--) 41 0008 3884FFFF addi r4,r4,-1 #n-- 42 000c 7CC53378 L1: mr r5,r6 #i 43 0010 48000039 bl DownHeap # downHeap(a, i, n); // r3,r5,r4 44 0014 34C6FFFF addic. r6,r6,-1 # // i--) 45 0018 4080FFF4 bge+ L1 # // i >= 0; 46 001c 80E30000 L2: lwz r7,0(r3) #a[0] for (i = n - 1; i > 0; i--) { // r4 = i 47 0020 548B103A slwi r11,r4,2 #4*i 48 0024 7CC3582E lwzx r6,r3,r11 # tmp = a[i]; 49 0028 7CE3592E stwx r7,r3,r11 # a[i] = a[0]; 50 002c 90C30000 stw r6,0(r3) # a[0] = tmp; 51 0030 38A00000 li r5,0 #k = 0 52 0034 3484FFFF addic. r4,r4,-1 #i-- (n--) 53 0038 48000011 bl DownHeap # downHeap(a, 0, i); // r3,r5,r4 54 003c 4082FFE0 bne+ L2 # } // i > 0 55 0040 7C0803A6 mtlr r0 #} 56 0044 4E800020 blr 57 0048 54AB103A DownHeap: slwi r11,r5,2 #4*k void downHeap(int *a, int k, int n)// r3,r5,r4 58 004c 7D03582E lwzx r8,r3,r11#tmp=a[k]{ int i,tmp;/* r7,8 */n--;//вече намалено 59 0050 548BF87E L3: srwi r11,r4,1 #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 60 0054 7C855840 cmplw cr1,r5,r11#k <= n / 2 (cr0 зает)? 61 0058 4185004C bgt- cr1,L5 #ако не, край на цикъла 62 005c 54A7083C slwi r7,r5,1 # i = 2 * k; 63 0060 54EB103A slwi r11,r7,2 #4*i 64 0064 7D635A14 add r11,r3,r11 #a + 4*i 65 0068 7C872040 cmplw cr1,r7,r4 # if (i < n 66 006c 40840018 bge cr1,L4 # && 67 0070 812B0000 lwz r9,0(r11) #a[i] 68 0074 814B0004 lwz r10,4(r11) #a[i+1] 69 0078 7C895000 cmpw cr1,r9,r10 # a[i] < a[i+1]) 70 007c 40840008 bge cr1,L4 71 0080 38E70001 addi r7,r7,1 # i++; 72 0084 54EB103A L4: slwi r11,r7,2 #4*i 73 0088 7D23582E lwzx r9,r3,r11 #a[i] 74 008c 7C884800 cmpw cr1,r8,r9 # if (tmp >= a[i]) 75 0090 40840014 bge cr1,L5 # break; 76 0094 54AB103A slwi r11,r5,2 #4*k 77 0098 7D23592E stwx r9,r3,r11 # a[k] = a[i]; 78 009c 7CE53B78 mr r5,r7 # } // k = i 79 00a0 4BFFFFB0 b L3 80 00a4 54AB103A L5: slwi r11,r5,2 #4*k 81 00a8 7D03592E stwx r8,r3,r11 # a[k] = tmp; 82 00ac 4E800020 blr #} SPARC GAS heapSort.s page 1 1 ! Подреди във възходящ ред масив от %i1 (%i1 > 2) думи със знак, указани от %i0 2 ! Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 ! average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort !void heapSort(int *a, int n) //%i0, %i1 38 heapSort: !{ int i, tmp; //%l2 (%i1), %l2 39 0000 9DE3BFA0 save %sp,-96,%sp !davidlitchfield.com/sparc_buffer_overflows.pdf 40 0004 A5366001 srl %i1,1,%l2 ! for (i = n / 2; i >= 0; i--) 41 0008 B2266001 sub %i1,1,%i1 !n-- 42 000c 40000012 L1: call DownHeap ! downHeap(a, i, n);//%i0,%l1,%i1 43 0010 A2100012 mov %l2,%l1 !i (ще се изпълни преди „call“!) 44 0014 A4A4A001 subcc %l2,1,%l2 ! // i--) 45 0018 1ABFFFFD bcc L1 ! // i >= 0; 46 001c 01000000 nop 47 0020 E6060000 L2: ld [%i0],%l3 !a[0] for (i = n - 1; i > 0; i--) {// %i1 = i 48 0024 A12E6002 sll %i1,2,%l0 !4*i 49 0028 E4060010 ld [%i0+%l0],%l2 ! tmp = a[i]; 50 002c E6260010 st %l3,[%i0+%l0] ! a[i] = a[0]; 51 0030 E4260000 st %l2,[%i0] ! a[0] = tmp; 52 0034 A2100000 clr %l1 !k = 0 53 0038 40000007 call DownHeap ! downHeap(a, 0, i);//%i0,%l1,%i1 54 003c B2266001 sub %i1,1,%i1 !i-- (n--; ще се изпълни преди „call“!) 55 0040 80A64000 cmp %i1,%g0 56 0044 12BFFFF7 bne L2 ! } // i > 0 57 0048 01000000 nop 58 004c 81C7E008 ret !}// ще се изпълни след „restore“! 59 0050 81E80000 restore 60 0054 A12C6002 DownHeap: sll %l1,2,%l0 !4*k void downHeap(int *a, int k, int n)//%i0,%l1,%i1 61 0058 E8060010 ld [%i0+%l0],%l4!tmp=a[k]{ int i,tmp;/*%l3,4 */n--;//вече намалено 62 005c A1366001 L3: srl %i1,1,%l0 !n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 63 0060 80A44010 cmp %l1,%l0 !k <= n / 2 ? 64 0064 18800014 bgu L5 !ако не, край на цикъла 65 0068 A72C6001 sll %l1,1,%l3 ! i = 2 * k; 66 006c A12CE002 sll %l3,2,%l0 !4*i 67 0070 80A4C019 cmp %l3,%i1 ! if (i < n 68 0074 1A800008 bcc L4 ! && 69 0078 A0060010 add %i0,%l0,%l0 !a + 4*i (ще се изпълни преди „bcc“!) 70 007c EA040000 ld [%l0],%l5 !a[i] 71 0080 EC042004 ld [%l0+4],%l6 !a[i+1] 72 0084 80A54016 cmp %l5,%l6 ! a[i] < a[i+1]) 73 0088 16800003 bge L4 74 008c 01000000 nop 75 0090 A604E001 add %l3,1,%l3 ! i++; 76 0094 A12CE002 L4: sll %l3,2,%l0 !4*i 77 0098 EA060010 ld [%i0+%l0],%l5 !a[i] 78 009c 80A50015 cmp %l4,%l5 ! if (tmp >= a[i]) 79 00a0 16800006 bge L6 ! break; 80 00a4 A12C6002 sll %l1,2,%l0 !4*k (изпълнява се преди „bge“!) 81 00a8 EA260010 st %l5,[%i0+%l0] ! a[k] = a[i]; 82 00ac A2100013 mov %l3,%l1 ! } // k = i 83 00b0 10BFFFEB ba L3 84 00b4 A12C6002 L5: sll %l1,2,%l0 !4*k 85 00b8 81C3E008 L6: retl 86 00bc E8260010 st %l4,[%i0+%l0] ! a[k] = tmp; }// изпълн.се преди „retl“! MIPS GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от $5 ($5 > 2) думи със знак, указани от $4 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 #/* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 #void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 #{ // най-големия възел в корена му 8 # int i, tmp; 9 # 10 # n--; // Премини към база 0 11 # for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 # i = 2 * k; // Ляв потомък 13 # if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 # i++; // левия и избери по-големия 15 # if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 # break; // на най-големия потомък, клонът е OK 17 # a[k] = a[i]; // Иначе потомъкът застава на мястото 18 # } // на родителя 19 # a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 #} // потомък, освен ако е по-голям от всички потомци 21 # 22 #void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 #{ // Сортиращо дърво, heap, tas: пирамида 24 # int i, tmp; 25 # 26 # for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 # downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 # for (i = n - 1; i > 0; i--) { 29 # tmp = a[i]; // Размени местата на максимума 30 # a[i] = a[0]; // и последния елемент на масива 31 # a[0] = tmp; 32 # downHeap(a, 0, i); // Препострой сортиращото дърво за 33 # } // неотсортираната част от масива 34 #} 35 #*/ 36 37 .ent heapSort 38 .global heapSort #void heapSort(int *a, int n) // $4, $5 39 heapSort: #{ int i, tmp; // $7 ($5), $7 40 0000 03E01021 MOVE $2,$31 #Съхрани $31, защото BAL ще го промени! 41 0004 00053842 SRL $7,$5,1 # for (i = n / 2; i >= 0; i--) 42 0008 24A5FFFF ADDIU $5,$5,-1 #n-- 43 L1: MOVE $6,$7 #i 44 000c 04110011 00E03021 BAL DownHeap # downHeap(a, i, n); // $4,$6,$5 45 0014 24E7FFFF ADDIU $7,$7,-1 # // i--) 46 0018 04E1FFFC 00000000 BGE $7,$0,L1 # // i >= 0; 47 0020 8C880000 L2: LW $8,0($4) #a[0] for (i = n - 1; i > 0; i--) { // $5 = i 48 0024 00051880 SLL $3,$5,2 #4*i 49 0028 00831821 ADDU $3,$4,$3 #a + 4*i 50 002c 8C670000 LW $7,0($3) # tmp = a[i]; 51 0030 AC680000 SW $8,0($3) # a[i] = a[0]; 52 0034 AC870000 SW $7,0($4) # a[0] = tmp; 53 0038 24060000 LI $6,0 #k = 0 54 ADDIU $5,$5,-1 #i-- (n--) 55 003c 04110005 24A5FFFF BAL DownHeap # downHeap(a, 0, i); // $4,$6,$5 56 0044 14A0FFF6 00000000 BNE $5,$0,L2 # } // i > 0 57 004c 00400008 00000000 JR $2 #} 58 0054 00061880 DownHeap: SLL $3,$6,2 #4*k void downHeap(int *a, int k, int n)// $4,$6,$5 59 0058 00831821 ADDU $3,$4,$3 #a + 4*k{ 60 005c 8C690000 LW $9,0($3) #tmp=a[k] int i,tmp;/* $8,9 */n--;//вече намалено 61 0060 00051842 L3: SRL $3,$5,1 #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 62 0064 0066082A 14200018 00000000 BGT $6,$3,L5 #k <= n / 2? 63 0070 00064040 SLL $8,$6,1 # i = 2 * k; 64 0074 00081880 SLL $3,$8,2 #4*i 65 0078 00831821 ADDU $3,$4,$3 #a + 4*i 66 007c 0105082A 10200007 00000000 BGE $8,$5,L4 # if (i < n 67 0088 8C6A0000 LW $10,0($3) #a[i] && 68 008c 8C6B0004 LW $11,4($3) #a[i+1] 69 0090 014B082A 10200002 00000000 BGE $10,$11,L4 # a[i] < a[i+1]) 70 009c 25080001 ADDIU $8,$8,1 # i++; 71 00a0 00081880 L4: SLL $3,$8,2 #4*i 72 00a4 00831821 ADDU $3,$4,$3 #a + 4*i 73 00a8 8C6A0000 LW $10,0($3) #a[i] if (tmp >= a[i]) 74 00ac 012A082A 10200006 00000000 BGE $9,$10,L5 # break; 75 00b8 00061880 SLL $3,$6,2 #4*k 76 00bc 00831821 ADDU $3,$4,$3 #a + 4*k 77 00c0 AC6A0000 SW $10,0($3) # a[k] = a[i]; 78 MOVE $6,$8 # } // k = i 79 00c4 1000FFE6 01003021 B L3 80 00cc 00061880 L5: SLL $3,$6,2 #4*k 81 00d0 00831821 ADDU $3,$4,$3 #a + 4*k 82 SW $9,0($3) # a[k] = tmp; 83 00d4 03E00008 AC690000 JR $31 #} 84 00dc 00000000 .end heapSort RISC-V GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от a1 (a1 > 2) думи със знак, указани от a0 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort #void heapSort(int *a, int n) // a0, a1 38 heapSort: #{ int i, tmp; // a3 (a1), a3 39 0000 93D61500 SRLI a3,a1,1 # for (i = n / 2; i >= 0; i--) 40 0004 FD15 ADDI a1,a1,-1 #n-- 41 0006 3686 L1: MV a2,a3 #i 42 0008 EF028002 JAL t0,DownHeap # downHeap(a, i, n); // a0,a2,a1 43 000c FD16 ADDI a3,a3,-1 # // i--) 44 000e E3DC06FE BGEZ a3,L1 # // i >= 0; 45 0012 1841 L2: LW a4,0(a0) #a[0] for (i = n - 1; i > 0; i--) { // a1 = i 46 0014 13932500 SLLI t1,a1,2 #4*i 47 0018 2A93 ADD t1,a0,t1 #a + 4*i 48 001a 83260300 LW a3,0(t1) # tmp = a[i]; 49 001e 2320E300 SW a4,0(t1) # a[i] = a[0]; 50 0022 14C1 SW a3,0(a0) # a[0] = tmp; 51 0024 0146 LI a2,0 #k = 0 52 0026 FD15 ADDI a1,a1,-1 #i-- (n--) 53 0028 EF028000 JAL t0,DownHeap # downHeap(a, 0, i); // a0,a2,a1 54 002c FDF1 BNEZ a1,L2 # } // i > 0 55 002e 8280 RET #} 56 0030 13132600 DownHeap: SLLI t1,a2,2 #4*k void downHeap(int *a, int k, int n)// a0,a2,a1 57 0034 2A93 ADD t1,a0,t1 #a + 4*k{ 58 0036 83270300 LW a5,0(t1) #tmp=a[k] int i,tmp;/* a4,5 */n--;//вече намалено 59 003a 13D31500 L3: SRLI t1,a1,1 #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 60 003e 634EC302 BGT a2,t1,L5 #k <= n / 2? 61 0042 13171600 SLLI a4,a2,1 # i = 2 * k; 62 0046 13132700 SLLI t1,a4,2 #4*i 63 004a 2A93 ADD t1,a0,t1 #a + 4*i 64 004c 6359B700 BGE a4,a1,L4 # if (i < n 65 0050 03280300 LW a6,0(t1) #a[i] && 66 0054 83284300 LW a7,4(t1) #a[i+1] 67 0058 63531801 BGE a6,a7,L4 # a[i] < a[i+1]) 68 005c 0507 ADDI a4,a4,1 # i++; 69 005e 13132700 L4: SLLI t1,a4,2 #4*i 70 0062 2A93 ADD t1,a0,t1 #a + 4*i 71 0064 03280300 LW a6,0(t1) #a[i] if (tmp >= a[i]) 72 0068 63D90701 BGE a5,a6,L5 # break; 73 006c 13132600 SLLI t1,a2,2 #4*k 74 0070 2A93 ADD t1,a0,t1 #a + 4*k 75 0072 23200301 SW a6,0(t1) # a[k] = a[i]; 76 0076 3A86 MV a2,a4 # } // k = i 77 0078 C9B7 J L3 78 007a 13132600 L5: SLLI t1,a2,2 #4*k 79 007e 2A93 ADD t1,a0,t1 #a + 4*k 80 0080 2320F300 SW a5,0(t1) # a[k] = tmp; 81 0084 8282 JR t0 #} Nios II GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от r5 (r5 > 2) думи със знак, указани от r4 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 #/* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 #void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 #{ // най-големия възел в корена му 8 # int i, tmp; 9 # 10 # n--; // Премини към база 0 11 # for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 # i = 2 * k; // Ляв потомък 13 # if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 # i++; // левия и избери по-големия 15 # if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 # break; // на най-големия потомък, клонът е OK 17 # a[k] = a[i]; // Иначе потомъкът застава на мястото 18 # } // на родителя 19 # a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 #} // потомък, освен ако е по-голям от всички потомци 21 # 22 #void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 #{ // Сортиращо дърво, heap, tas: пирамида 24 # int i, tmp; 25 # 26 # for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 # downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 # for (i = n - 1; i > 0; i--) { 29 # tmp = a[i]; // Размени местата на максимума 30 # a[i] = a[0]; // и последния елемент на масива 31 # a[0] = tmp; 32 # downHeap(a, 0, i); // Препострой сортиращото дърво за 33 # } // неотсортираната част от масива 34 #} 35 #*/ 36 37 .global heapSort #void heapSort(int *a, int n) // r4, r5 38 heapSort: #{ int i, tmp; // r7 (r5), r7 39 0000 3A8805F8 MOV r2,ra #Съхрани ra, защото CALL ще го промени! 40 0004 7AD00E28 SRLI r7,r5,1 # for (i = n / 2; i >= 0; i--) 41 0008 C4FF7F29 SUBI r5,r5,1 #n-- 42 000c 3A880D38 L1: MOV r6,r7 #i 43 0010 00000000 CALL DownHeap # downHeap(a, i, n); // r4,r6,r5 44 0014 C4FFFF39 SUBI r7,r7,1 # // i--) 45 0018 0EFC3F38 BGE r7,r0,L1 # // i >= 0; 46 001c 17000022 L2: LDW r8,(r4) #a[0] for (i = n - 1; i > 0; i--) { // r5 = i 47 0020 BA900628 SLLI r3,r5,2 #4*i 48 0024 3A88C720 ADD r3,r4,r3 #a + 4*i 49 0028 1700C019 LDW r7,(r3) # tmp = a[i]; 50 002c 1500001A STW r8,(r3) # a[i] = a[0]; 51 0030 1500C021 STW r7,(r4) # a[0] = tmp; 52 0034 14008001 MOVUI r6,0 #k = 0 53 0038 C4FF7F29 SUBI r5,r5,1 #i-- (n--) 54 003c 00000000 CALL DownHeap # downHeap(a, 0, i); // r4,r6,r5 55 0040 1EF63F28 BNE r5,r0,L2 # } // i > 0 56 0044 3A680010 JMP r2 #} 57 0048 BA900630 DownHeap: SLLI r3,r6,2 #4*k void downHeap(int *a, int k, int n)// r4,r6,r5 58 004c 3A88C720 ADD r3,r4,r3 #a + 4*k{ 59 0050 1700401A LDW r9,(r3) #tmp=a[k] int i,tmp;/* r8,9 */n--;//вече намалено 60 0054 7AD00628 L3: SRLI r3,r5,1 #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 61 0058 16118019 BGT r6,r3,L5 #k <= n / 2? 62 005c 7A901030 SLLI r8,r6,1 # i = 2 * k; 63 0060 BA900640 SLLI r3,r8,2 #4*i 64 0064 3A88C720 ADD r3,r4,r3 #a + 4*i 65 0068 0E044041 BGE r8,r5,L4 # if (i < n 66 006c 1700801A LDW r10,(r3) #a[i] && 67 0070 1701C01A LDW r11,4(r3) #a[i+1] 68 0074 0E01C052 BGE r10,r11,L4 # a[i] < a[i+1]) 69 0078 44000042 ADDI r8,r8,1 # i++; 70 007c BA900640 L4: SLLI r3,r8,2 #4*i 71 0080 3A88C720 ADD r3,r4,r3 #a + 4*i 72 0084 1700801A LDW r10,(r3) #a[i] if (tmp >= a[i]) 73 0088 0E05804A BGE r9,r10,L5 # break; 74 008c BA900630 SLLI r3,r6,2 #4*k 75 0090 3A88C720 ADD r3,r4,r3 #a + 4*k 76 0094 1500801A STW r10,(r3) # a[k] = a[i]; 77 0098 3A880D40 MOV r6,r8 # } // k = i 78 009c 06ED3F00 BR L3 79 00a0 BA900630 L5: SLLI r3,r6,2 #4*k 80 00a4 3A88C720 ADD r3,r4,r3 #a + 4*k 81 00a8 1500401A STW r9,(r3) # a[k] = tmp; 82 00ac 3A2800F8 RET #} Xtensa GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от a3 (a3 > 2) думи със знак, указани от a2 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort #void heapSort(int *a, int n) // a2, a3 38 heapSort: #{ int i, tmp; // a5 (a3), a5 39 0000 BD00 MOV a11,a0 #Съхрани a0, защото CALL0 ще го промени! 40 0002 305141 SRLI a5,a3,1 # for (i = n / 2; i >= 0; i--) 41 0005 32C3FF ADDI a3,a3,-1 #n-- 42 0008 4D05 L1: MOV a4,a5 #i 43 000a 010000C0 0000 CALL0 DownHeap # downHeap(a, i, n); // a2,a4,a3 44 0010 0B55 ADDI a5,a5,-1 # // i--) 45 0012 D625FF BGEZ a5,L1 # // i >= 0; 46 0015 6802 L2: L32I a6,a2,0 #a[0] for (i = n - 1; i > 0; i--) { // a3 = i 47 0017 20A3A0 ADDX4 a10,a3,a2 #a + 4*i 48 001a 580A L32I a5,a10,0 # tmp = a[i]; 49 001c 690A S32I a6,a10,0 # a[i] = a[0]; 50 001e 5902 S32I a5,a2,0 # a[0] = tmp; 51 0020 42A000 MOVI a4,0 #k = 0 52 0023 32C3FF ADDI a3,a3,-1 #i-- (n--) 53 0026 010000C0 0000 CALL0 DownHeap # downHeap(a, 0, i); // a2,a4,a3 54 002c 5653FE BNEZ a3,L2 # } // i > 0 55 002f A00B00 JX a11 #} 56 0032 0000 .align 4 57 0034 20A4A0 DownHeap: ADDX4 a10,a4,a2#a + 4*kvoid downHeap(int *a, int k, int n)// a2,a4,a3 58 0037 780A L32I a7,a10,0#tmp=a[k]{ int i,tmp;/* a6,5 */n--;//вече намалено 59 0039 30A141 L3: SRLI a10,a3,1#n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 60 003c 472A24 BLT a10,a4,L5#k <= n / 2? 61 003f F06411 SLLI a6,a4,1 # i = 2 * k; 62 0042 20A6A0 ADDX4 a10,a6,a2 #a + 4*i 63 0045 37A608 BGE a6,a3,L4 # if (i < n 64 0048 880A L32I a8,a10,0 #a[i] && 65 004a 981A L32I a9,a10,4 #a[i+1] 66 004c 97A801 BGE a8,a9,L4 # a[i] < a[i+1]) 67 004f 1B66 ADDI a6,a6,1 # i++; 68 0051 20A6A0 L4: ADDX4 a10,a6,a2 #a + 4*i 69 0054 880A L32I a8,a10,0 #a[i] if (tmp >= a[i]) 70 0056 87A70A BGE a7,a8,L5 # break; 71 0059 20A4A0 ADDX4 a10,a4,a2 #a + 4*k 72 005c 890A S32I a8,a10,0 # a[k] = a[i]; 73 005e 4D06 MOV a4,a6 # } // k = i 74 0060 46F5FF00 J L3 75 0064 20A4A0 L5: ADDX4 a10,a4,a2 #a + 4*k 76 0067 790A S32I a7,a10,0 # a[k] = tmp; 77 0069 0DF0 RET #} 88K GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от r3 (r3 > 2) думи със знак, указани от r2 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималния 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global _heapSort #void heapSort(int *a, int n) // r2, r3 38 0000 F5415800 _heapSort: #{ int i, tmp; // r5 (r3), r5 39 0004 F0A39801 or r10,r1,r0 #Съхрани r1, защото bsr ще го промени! 40 0008 64630001 extu r5,r3,0<1> # for (i = n / 2; i >= 0; i--) 41 000c F4855800 subu r3,r3,1 #n-- 42 0010 C800000C L1: or r4,r5,r0 #i 43 0014 64A50001 bsr DownHeap # downHeap(a, i, n); // r2,r4,r3 44 0018 E865FFFD subu r5,r5,1 # // i--) 45 001c F4C21400 bcnd ge0,r5,L1 # // i >= 0; 46 0020 F4A21603 L2: ld r6,r2,r0 #a[0] for (i = n - 1; i > 0; i--) { // r3 = i 47 0024 F4C22603 ld r5,r2[r3] # tmp = a[i]; 48 0028 F4A22400 st r6,r2[r3] # a[i] = a[0]; 49 002c F4805800 st r5,r2,r0 # a[0] = tmp; 50 0030 64630001 or r4,r0,r0 #k = 0 51 0034 C8000003 subu r3,r3,1 #i-- (n--) 52 0038 E823FFF9 bsr DownHeap # downHeap(a, 0, i); // r2,r4,r3 53 003c F400C00A bcnd gt0,r3,L2 # } // i > 0 54 0040 F4E21604 jmp r10 #}void downHeap(int *a, int k, int n)// r2,r4,r3 55 0044 F1039801 DownHeap: ld r7,r2[r4] #{ __ int i,tmp;/* r6,7 */n--;//вече намалено 56 0048 F5047C08 L3: extu r8,r3,0<1> #n/2 \_ for (tmp = a[k]; k <= n / 2; k = i) { 57 004c D9080010 cmp r8,r4,r8 #k <= n / 2? 58 0050 F0C4A001 bb1 hi,r8,L5 #ако не, край на цикъла 59 0054 F5067C03 mak r6,r4,0<1> # i = 2 * k; 60 0058 D9680007 cmp r8,r6,r3 # if (i < n 61 005c F5021606 bb1 hs,r8,L4 # && 62 0060 61260001 ld r8,r2[r6] #a[i] 63 0064 F5221609 addu r9,r6,1 #i+1 64 0068 F5287C09 ld r9,r2[r9] #a[i+1] 65 006c D8E90002 cmp r9,r8,r9 # a[i] < a[i+1]) 66 0070 60C60001 bb1 ge,r9,L4 67 0074 F5021606 addu r6,r6,1 # i++; 68 0078 F5277C08 L4: ld r8,r2[r6] #a[i] 69 007c D8E90004 cmp r9,r7,r8 # if (tmp >= a[i]) 70 0080 F5022604 bb1 ge,r9,L5 # break; 71 0084 F4865800 st r8,r2[r4] # a[k] = a[i]; 72 0088 C3FFFFEF or r4,r6,r0 # } // k = i 73 008c F4E22604 br L3 74 0090 F400C001 L5: st r7,r2[r4] # a[k] = tmp; jmp r1 #} Or1k GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от R4 (R4 > 2) думи със знак, указани от R3 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort #void heapSort(int *a, int n) //R3, R4 38 heapSort: #{ int i, tmp; //R7 (R4), R7 39 0000 E1E04804 L.OR R15,R0,LR #съхрани LR, защото „L.JAL“ ще го промени! 40 0004 B8E40041 L.SRLI R7,R4,1 # for (i = n / 2; i >= 0; i--) 41 0008 9C84FFFF L.ADDI R4,R4,-1 #n-- 42 000c 04000012 L1: L.JAL DownHeap # downHeap(a, i, n);//R3, R6, R4 43 0010 E0C70004 L.OR R6,R7,R0 #i (ще се изпълни преди „L.JAL“!) 44 0014 E4470000 L.SFGTU R7,R0 # // i >= 0; 45 0018 13FFFFFD L.BF L1 #ще се изпълни след „L.ADDI“! 46 001c 9CE7FFFF L.ADDI R7,R7,-1 # i--) 47 0020 85030000 L2: L.LWZ R8,0(R3) #a[0] for (i = n - 1; i > 0; i--) {// R4 = i 48 0024 B8A40002 L.SLLI R5,R4,2 #4*i 49 0028 E0A32800 L.ADD R5,R3,R5 #a + 4*i 50 002c 84E50000 L.LWZ R7,0(R5) # tmp = a[i]; 51 0030 D4054000 L.SW 0(R5),R8 # a[i] = a[0]; 52 0034 D4033800 L.SW 0(R3),R7 # a[0] = tmp; 53 0038 E0C00004 L.OR R6,R0,R0 #k = 0 54 003c 04000006 L.JAL DownHeap # downHeap(a, 0, i);//R3,R6,R4 55 0040 9C84FFFF L.ADDI R4,R4,-1 #i-- (n--; ще се изпълни преди „L.JAL“!) 56 0044 E4240000 L.SFNE R4,R0 # // i > 0 57 0048 13FFFFF6 L.BF L2 # } 58 004c 15000000 L.NOP 0 59 0050 44007800 L.JR R15 #} //ще се изпълни след „L.SLLI“! 60 0054 B8A60002 DownHeap: L.SLLI R5,R6,2 #4*k void downHeap(int *a, int k, int n)//R3,R6,R4 61 0058 E0A32800 L.ADD R5,R3,R5 #a + 4*k{ 62 005c 85650000 L.LWZ R11,0(R5)#tmp=a[k] int i,tmp;/*R8,11*/n--;//вече намалено 63 0060 B8A40041 L3: L.SRLI R5,R4,1 #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 64 0064 E4A62800 L.SFLEU R6,R5 #k <= n / 2 ? 65 0068 0C000016 L.BNF L5 #ако не, край на цикъла (ще се изпълни след „L.SLLI“!) 66 006c B9060001 L.SLLI R8,R6,1 # i = 2 * k; 67 0070 B8A80002 L.SLLI R5,R8,2 #4*i 68 0074 E4882000 L.SFLTU R8,R4 # if (i < n 69 0078 0C000008 L.BNF L4 # && 70 007c E0A32800 L.ADD R5,R3,R5 #a + 4*i (ще се изпълни преди „L.BNF“!) 71 0080 85850000 L.LWZ R12,0(R5) #a[i] 72 0084 85A50004 L.LWZ R13,4(R5) #a[i+1] 73 0088 E58C6800 L.SFLTS R12,R13 # a[i] < a[i+1]) 74 008c 0C000003 L.BNF L4 75 0090 15000000 L.NOP 0 76 0094 9D080001 L.ADDI R8,R8,1 # i++; 77 0098 B8A80002 L4: L.SLLI R5,R8,2 #4*i 78 009c E0A32800 L.ADD R5,R3,R5 #a + 4*i 79 00a0 85850000 L.LWZ R12,0(R5) #a[i] 80 00a4 E56B6000 L.SFGES R11,R12 # if (tmp >= a[i]) 81 00a8 10000007 L.BF L6 # break; 82 00ac B8A60002 L.SLLI R5,R6,2 #4*k (ще се изпълни преди „L.BF“!) 83 00b0 E0A32800 L.ADD R5,R3,R5 #a + 4*k 84 00b4 D4056000 L.SW 0(R5),R12 # a[k] = a[i]; 85 00b8 E0C80004 L.OR R6,R8,R0 # } // k = i 86 00bc 03FFFFE9 L.J L3 #ще се изпълни след „L.SLLI“!) 87 00c0 B8A60002 L5: L.SLLI R5,R6,2 #4*k 88 00c4 E0A32800 L6: L.ADD R5,R3,R5 #a + 4*k 89 00c8 44004800 L.JR LR 90 00cc D4055800 L.SW 0(R5),R11 # a[k] = tmp; }// изпълн.се преди „L.JR“! Xilinx MicroBlaze GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от R6 (R6 > 2) думи със знак, указани от R5 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort #void heapSort(int *a, int n) // R5, R6 38 heapSort: #{ int i, tmp; // R8 (R6), R8 39 0000 41000691 SRL R8,R6 # for (i = n / 2; i >= 0; i--) 40 0004 FFFFC620 ADDI R6,R6,-1 #n-- 41 0008 380074B8 L1: BRLID R3,DownHeap#изп.се след OR! downHeap(a, i, n); // R5,R7,R6 42 000c 0000E880 OR R7,R8,R0 #i 43 0010 FFFF0821 ADDI R8,R8,-1 # // i--) 44 0014 F4FFA8BC BGEI R8,L1 # // i >= 0; 45 0018 000025E9 L2: LWI R9,R5,0 #a[0] for (i = n - 1; i > 0; i--) { // R6 = i 46 001c 02048664 BSLLI R4,R6,2 #4*i 47 0020 002005C9 LW R8,R5,R4 # tmp = a[i]; 48 0024 002025D9 SW R9,R5,R4 # a[i] = a[0]; 49 0028 000005D9 SW R8,R5,R0 # a[0] = tmp; 50 002c 0000E080 OR R7,R0,R0 #k = 0 51 0030 100074B8 BRLID R3,DownHeap#изп.се след ADDI! downHeap(a, 0, i); // R5,R7,R6 52 0034 FFFFC620 ADDI R6,R6,-1 #i-- (n--) 53 0038 E0FF26BC BNEI R6,L2 # } // i > 0 54 003c 08000FB6 RTSD R15,8 #}// след BSLLI 55 0040 02048764 DownHeap: BSLLI R4,R7,2 #4*k void downHeap(int *a, int k, int n)// R5,R7,R6 56 0044 002045C9 LW R10,R5,R4#tmp=a[k]{ int i,tmp;/* R9,10*/n--;//вече намалено 57 0048 41008690 L3: SRL R4,R6 #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 58 004c 03204716 CMPU R18,R7,R4#k <= n / 2 ? 59 0050 4C0052BC BLTI R18,L5 #ако не, край на цикъла 60 0054 00382701 ADD R9,R7,R7 # i = 2 * k; 61 0058 02048964 BSLLI R4,R9,2 #4*i 62 005c 00208500 ADD R4,R5,R4 #a + 4*i 63 0060 03484616 CMPU R18,R6,R9 # if (i < n 64 0064 1800B2BC BGEI R18,L4 # && 65 0068 000064E9 LWI R11,R4,0 #a[i] 66 006c 040084E9 LWI R12,R4,4 #a[i+1] 67 0070 01584C16 CMP R18,R12,R11 # a[i] < a[i+1]) 68 0074 0800B2BC BGEI R18,L4 69 0078 01002921 ADDI R9,R9,1 # i++; 70 007c 02048964 L4: BSLLI R4,R9,2 #4*i 71 0080 002065C9 LW R11,R5,R4 #a[i] 72 0084 01504B16 CMP R18,R11,R10 # if (tmp >= a[i]) 73 0088 1400B2BC BGEI R18,L5 # break; 74 008c 02048764 BSLLI R4,R7,2 #4*k 75 0090 002065D9 SW R11,R5,R4 # a[k] = a[i]; 76 0094 0000E980 OR R7,R9,R0 # } // k = i 77 0098 B0FF00B8 BRI L3 78 009c 02048764 L5: BSLLI R4,R7,2 #4*k 79 00a0 080003B6 RTSD R3,8 # 80 00a4 002045D9 SW R10,R5,R4 # a[k] = tmp; }// изпълн.се преди „RTSD“! HPPA GAS heapSort.s page 1 1 ; Подреди във възходящ ред масив от R25 (R25 > 2) думи със знак, указани от R26 2 ; Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 ; average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 .text 37 .global heapSort ; void heapSort(int *a, int n) //R26, R25 38 heapSort: ; { | int i, tmp; //R23 (25), R23 39 0000 D3200BD7 SHD %R0,%R25,1,%R23 ; | for (i = n / 2; i >= 0; i--) 40 0004 B73907FF ADDI -1,%R25,%R25 ; n-- | 41 0008 EBE00060 L1: BL DOWNHEAP,%R31;изп.се след COPY downHeap(a, i, n); //26,22,25 42 000c 08170256 COPY %R23,%R22 ; i | 43 0010 AEFF5FE5 ADDIBF,< -1,%R23,L1 ;изп.се след LDI // i >= 0; i--) 44 0014 34160000 L2: LDI 0,%R22 ; k = 0 | for (i = n - 1; i > 0; i--) {//R25: i 45 0018 0B590A9C SH2ADDL %R25,%R26,%R28 ;адр.отм. 46 001c 0F801097 LDW 0(%R28),%R23 ; | tmp = a[i]; 47 0020 0F40109D LDW 0(%R26),%R29 ; =a[0] | a[i] = a[0]; 48 0024 0F571280 STW %R23,0(%R26) ; | a[0] = tmp; 49 0028 0F9D1280 STW %R29,0(%R28) ; a[i]= | 50 002c EBE00018 BL DOWNHEAP,%R31;изп.се след ADDI downHeap(a, 0, i); //26,22,25 51 0030 B73907FF ADDI -1,%R25,%R25 ; i(n)--| // i > 0; 52 0034 8F203FB5 COMIBF,= 0,%R25,L2 ; | } 53 0038 08000240 NOP ; } 54 003c E840C002 BV,N (%R2) ; void downHeap(int *a, int k, int n)//26,22,25 55 0040 0F562081 DOWNHEAP: LDWX,S %R22(%R26),%R1 ; { | int i,tmp;/*24,1*/n--;//вече намалено 56 0044 D3200BD5 L3: SHD %R0,%R25,1,%R21 ; | for (tmp = a[k]; k <= n / 2; k = i) { 57 0048 8AB66060 COMBF,<= %R22,%R21,L5 ; | // k <= n / 2 58 004c 08160A58 SH1ADDL %R22,%R0,%R24;изп.се преди COMBF i = 2 * k; 59 0050 8B384020 COMBF,< %R24,%R25,L4 ; i и n < 2^31 if (i < n && 60 0054 0B580A95 SH2ADDL %R24,%R26,%R21;изп.се преди COMBF 61 0058 0EA01094 LDW 0(%R21),%R20 ; a[i] | 62 005c 0EA81093 LDW 4(%R21),%R19 ; a[i+1]| 63 0060 0A745880 COMCLR,>= %R20,%R19,%R0 ; | a[i] < a[i+1]) 64 0064 B7180002 ADDI 1,%R24,%R24 ; | i++; 65 0068 0F582094 L4: LDWX,S %R24(%R26),%R20 ; a[i] | 66 006c 80346018 COMBT,<= %R20,%R1,L5 ; | if (tmp >= a[i]) break; 67 0070 0B560A95 SH2ADDL %R22,%R26,%R21;изп.се преди COMBT 68 0074 0EB41280 STW %R20,0(%R21) ; | a[k] = a[i]; 69 0078 08180256 COPY %R24,%R22 ; k = i | } 70 007c E81F1F87 B,N L3 ; | 71 0080 0B560A95 L5: SH2ADDL %R22,%R26,%R21 ;адр.отм. 72 0084 0EA11280 STW %R1,0(%R21) ; | a[k] = tmp; 73 0088 EBE0C002 BV,N (%R31) ; } 73 00000000 Renesas / SuperH SH GAS Little Endian heapSort.s page 1 1 ! Подреди във възходящ ред масив от R5 (R5 > 2) думи със знак, указани от R4 2 ! Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 ! average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort 38 heapSort: !void heapSort(int *a, int n) // R4 -> R0, R5 39 0000 4360 MOV R4,R0 !{ int i, tmp; // R6 (R5), R6 40 0002 224F STS.L PR,@-SP!Съхрани PR, защото BSR ще го промени! 41 0004 5366 MOV R5,R6 ! for (i = n 42 0006 0146 SHLR R6 ! / 2; i >= 0; i--) 43 0008 FF75 ADD #-1,R5 !n-- 44 000a 10B0 L1: BSR DownHeap ! downHeap(a, i, n); // R0,R4,R5 45 000c 6364 MOV R6,R4 !i (изпълнява се преди „BSR“!) 46 000e FF76 ADD #-1,R6 ! // i--) 47 0010 1146 CMP/PZ R6 !i < 2^31 // i >= 0; 48 0012 FA89 BT L1 49 0014 0267 L2: MOV.L @R0,R7 !a[0] for (i = n - 1; i > 0; i--) { // R5 = i 50 0016 5361 MOV R5,R1 51 0018 0841 SHLL2 R1 !4*i 52 001a 1E06 MOV.L @(R0,R1),R6 ! tmp = a[i]; 53 001c 7601 MOV.L R7,@(R0,R1) ! a[i] = a[0]; 54 001e 6220 MOV.L R6,@R0 ! a[0] = tmp; 55 0020 00E4 MOV #0,R4 !k = 0 56 0022 04B0 BSR DownHeap !изпълн.се след „ADD“! downHeap(a, 0, i); // R0,R4,R5 57 0024 FF75 ADD #-1,R5 !i-- (n--) 58 0026 1545 CMP/PL R5 !i < 2^31 // i > 0 59 0028 F489 BT L2 ! } 60 002a 264F LDS.L @SP+,PR!Възст.PR } 61 002c 0B00 RTS !изпълнява се след „MOV“ 62 002e 4361 DownHeap: MOV R4,R1 !void downHeap(int *a, int k, int n)// R0,R4,R5 63 0030 0841 SHLL2 R1 !4*k { 64 0032 1E03 MOV.L @(R0,R1),R3 !tmp=a[k] int i,tmp;/* R7,3 */n--;//вече намалено 65 0034 5361 L3: MOV R5,R1 !n 66 0036 0141 SHLR R1 ! / 2 for (tmp = a[k]; k <= n / 2; k = i) { 67 0038 4231 CMP/HS R4,R1 !k <= n / 2 ? 68 003a 158B BF L5 !ако не, край на цикъла 69 003c 4367 MOV R4,R7 70 003e 0047 SHLL R7 ! i = 2 * k; 71 0040 7361 MOV R7,R1 72 0042 0841 SHLL2 R1 !4*i 73 0044 0C31 ADD R0,R1 !a + 4*i 74 0046 7635 CMP/HI R7,R5 ! if (i < n 75 0048 048B BF L4 ! && 76 004a 1262 MOV.L @R1,R2 !a[i] 77 004c 1151 MOV.L @(4,R1),R1 !a[i+1] 78 004e 2731 CMP/GT R2,R1 ! a[i] < a[i+1]) 79 0050 008B BF L4 80 0052 0177 ADD #1,R7 ! i++; 81 0054 7361 L4: MOV R7,R1 82 0056 0841 SHLL2 R1 !4*i 83 0058 1E02 MOV.L @(R0,R1),R2 !a[i] 84 005a 2333 CMP/GE R2,R3 ! if (tmp >= a[i]) 85 005c 0489 BT L5 ! break; 86 005e 4361 MOV R4,R1 87 0060 0841 SHLL2 R1 !4*k 88 0062 2601 MOV.L R2,@(R0,R1) ! a[k] = a[i]; 89 0064 7364 MOV R7,R4 ! } // k = i 90 0066 E58B BF L3 !T=0 91 0068 4361 L5: MOV R4,R1 92 006a 0841 SHLL2 R1 !4*k 93 006c 0B00 RTS !изпълнява се след „MOV.L“ 94 006e 3601 MOV.L R3,@(R0,R1) !} a[k] = tmp; GAS for CRIS heapSort.s page 1 1 ; Подреди във възходящ ред масив от R11 (R11 > 2) думи със знак, указани от R10 2 ; Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 ; average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort ;void heapSort(int *a, int n) //R10, R11 38 heapSort: ;{ int i, tmp; //R2 (R11), R2 39 0000 9CE2 SUBQ 28,$SP ; Съхрани R5–R1 (ETRAX FS Designer’s Reference, стр.212 40 0002 FE6B MOVEM $R6,[$SP] 41 0004 6B26 MOVE.D $R11,$R2 42 0006 E123 LSRQ 1,$R2 ; for (i = n / 2; i >= 0; i--) 43 0008 81B2 SUBQ 1,$R11 ;n-- 44 000a BF7E2C00 0000 L1: BAS DownHeap,$MOF ; downHeap(a, i, n);//R10,R6,R11 45 0010 6266 MOVE.D $R2,$R6 ;i (ще се изпълни преди „BAS“!) 46 0012 8122 SUBQ 1,$R2 ; // i--) 47 0014 F700 BHS L1 ; // i >= 0; 48 0016 B005 NOP 49 0018 6A3A L2: MOVE.D [$R10],$R3 ;a[0] for (i = n - 1; i > 0; i--) {// R11 = i 50 001a 6AB5 ADDI $R11.D,$R10,$ACR;a+4*i 51 001c 6F2A MOVE.D [$ACR],$R2 ; tmp = a[i]; 52 001e EF3B MOVE.D $R3,[$ACR] ; a[i] = a[0]; 53 0020 EA2B MOVE.D $R2,[$R10] ; a[0] = tmp; 54 0022 7686 CLEAR.D $R6 ;k = 0 55 0024 BF7E1200 0000 BAS DownHeap,$MOF ; downHeap(a, 0, i);//R10,R6,R11 56 002a 81B2 SUBQ 1,$R11 ;i-- (n--; ще се изпълни преди „BAS“!) 57 002c C0B2 CMPQ 0,$R11 58 002e EB20 BNE L2 ; } // i > 0 59 0030 B005 NOP 60 0032 F0B9 RET ;}// ще се изпълни след „MOVEM“! 61 0034 BE6F MOVEM [$SP+],$R6; Изпълнява се преди „RET“! 62 0036 6A65 DownHeap: ADDI $R6.D,$R10,$ACR ;void downHeap(int *a, int k, int n)//R10,R6,11 63 0038 6F4A MOVE.D [$ACR],$R4;tmp=a[k]{ 64 003a 6B56 L3: MOVE.D $R11,$R5 ; int i,tmp;/*R3,4 */n--;//вече намалено 65 003c E153 LSRQ 1,$R5 ;n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 66 003e E566 CMP.D $R5,$R6 ;k <= n / 2 ? 67 0040 2690 BHI L5 ;ако не, край на цикъла 68 0042 6636 MOVE.D $R6,$R3 69 0044 C133 LSLQ 1,$R3 ; i = 2 * k; 70 0046 EB36 CMP.D $R11,$R3 ; if (i < n 71 0048 0E00 BHS L4 ; && 72 004a 6A35 ADDI $R3.D,$R10,$ACR ;a+4*i (ще се изпълни преди „BHS“!) 73 004c BF1B MOVEM [$ACR],$R1 ;a[i],a[i+1] 74 004e E106 CMP.D $R1,$R0 ; a[i] < a[i+1]) 75 0050 06A0 BGE L4 76 0052 B005 NOP 77 0054 0132 ADDQ 1,$R3 ; i++; 78 0056 6A35 L4: ADDI $R3.D,$R10,$ACR ;a+4*i 79 0058 6F0A MOVE.D [$ACR],$R0 ;a[i] 80 005a E046 CMP.D $R0,$R4 ; if (tmp >= a[i]) 81 005c 0CA0 BGE L6 ; break; 82 005e 6A65 ADDI $R6.D,$R10,$ACR ;a+4*k (изпълнява се преди „BGE“!) 83 0060 EF0B MOVE.D $R0,[$ACR] ; a[k] = a[i]; 84 0062 6366 MOVE.D $R3,$R6 ; } // k = i 85 0064 D7E0 BA L3 86 0066 6A65 L5: ADDI $R6.D,$R10,$ACR ;a+4*k 87 0068 F079 L6: JUMP $MOF 88 006a EF4B MOVE.D $R4,[$ACR] ; a[k] = tmp; }// изпълн.се преди „JUMP“! BFIN GAS heapSort.s page 1 1 # Подреди във възходящ ред масив от R1 (R1 > 2) думи със знак, указани от R0 2 # Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 # average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global _heapSort #void heapSort(int *a, int n) // R0->P0, R1->P1 38 _heapSort: #{ int i, tmp; // P3 (P1), R1 39 0000 E305 [--SP] = (R7:4, P5:3); #Съхрани R4–R7/P3–P5 (82-000410-03, стр. 1-433) 40 0002 3F31 R7 = RETS; #и адреса на връщане, защото CALL ще го промени 41 0004 0032 P0 = R0; #a 42 0006 0932 P1 = R1; #n 43 0008 0B45 P3 = P1 >> 1; # for (i = n / 2; i >= 0; i--) 44 000a F96F P1 += -1; #n-- 45 000c 5332 L_1: P2 = P3; #i 46 000e 00E31300 CALL DownHeap; # downHeap(a, i, n); // P0,P2,P1 47 0012 CB0D CC = P3 < 1 (IU); 48 0014 FB6F P3 += -1; # // i--) 49 0016 FB13 IF !CC JUMP L_1; # // i >= 0; 50 0018 0091 L_2: R0 = [P0]; #a[0] for (i = n - 1; i > 0; i--) { // P1 = i 51 001a 485F P5 = P0 + (P1 << 2); #a + 4*i 52 001c 2991 R1 = [P5]; # tmp = a[i]; 53 001e 2893 [P5] = R0; # a[i] = a[0]; 54 0020 0193 [P0] = R1; # a[0] = tmp; 55 0022 0268 P2 = 0 (X); #k = 0 56 0024 F96F P1 += -1; #i-- (n--) 57 0026 00E30700 CALL DownHeap; # downHeap(a, 0, i); // P0,P2,P1 58 002a 410C CC = P1 == 0; 59 002c F613 IF !CC JUMP L_2; # } // i > 0 60 002e 3F38 RETS = R7; #Възстанови адреса на връщане 61 0030 A305 (R7:4, P5:3) = [SP++]; #и съхранените регистри 62 0032 1000 RTS; #} 63 0034 505F DownHeap: P5 = P0 + (P2 << 2);#a+4*kvoid downHeap(int *a,int k,int n)//P0,P2,P1 64 0036 2A91 R2 = [P5]; #tmp=a[k]{ int i,tmp;/* P4,R2*/n--;//вече намалено 65 0038 0D45 L_3: P5 = P1 >> 1; #n / 2 for (tmp = a[k]; k <= n / 2; k = i) { 66 003a 6A0A CC = P2 <= P5 (IU);#k <= n / 2? 67 003c 1210 IF !CC JUMP L_5; 68 003e 125B P4 = P2 << 1; # i = 2 * k; 69 0040 605F P5 = P0 + (P4 << 2); #a + 4*i 70 0042 CC09 CC = P4 < P1 (IU); # if (i < n 71 0044 0610 IF !CC JUMP L_4; 72 0046 2B91 R3 = [P5]; #a[i] && 73 0048 6CA0 R4 = [P5 + 4]; #a[i+1] 74 004a A308 CC = R3 < R4; # a[i] < a[i+1]) 75 004c 0210 IF !CC JUMP L_4; 76 004e 0C6C P4 += 1; # i++; 77 0050 605F L_4: P5 = P0 + (P4 << 2); #a + 4*i 78 0052 2B91 R3 = [P5]; #a[i] 79 0054 1309 CC = R3 <= R2; # if (tmp >= a[i]) 80 0056 0518 IF CC JUMP L_5; # break; 81 0058 505F P5 = P0 + (P2 << 2); #a + 4*k 82 005a 2B93 [P5] = R3; # a[k] = a[i]; 83 005c 5432 P2 = P4; # } // k = i 84 005e ED2F JUMP L_3; 85 0060 505F L_5: P5 = P0 + (P2 << 2); #a + 4*k 86 0062 2A93 [P5] = R2; # a[k] = tmp; 87 0064 10000000 RTS; #} Hexagon GAS heapSort.s page 1 1 // Подреди във възходящ ред масив от R1 (R1 > 2) думи със знак, указани от R0 2 // Ingo Wegener: Bottom-up Heapsort, a new variant of Heapsort beating, on an 3 // average, Quicksort (if n is not very small), Theoretical Comp. Science '93 4 5 /* Пирамида – двоично дърво, в което родителят е не по-малък от потомците си. 6 void downHeap(int *a, int k, int n) // Прегледай поддървото и премести 7 { // най-големия възел в корена му 8 int i, tmp; 9 10 n--; // Премини към база 0 11 for (tmp = a[k]; k <= n / 2; k = i) { // В корена запомни родителя 12 i = 2 * k; // Ляв потомък 13 if (i < n && a[i] < a[i+1]) // Ако има десен, сравни го с 14 i++; // левия и избери по-големия 15 if (tmp >= a[i]) // Ако родителят е по-голям или равен 16 break; // на най-големия потомък, клонът е OK 17 a[k] = a[i]; // Иначе потомъкът застава на мястото 18 } // на родителя 19 a[k] = tmp; // Накрая родителят си разменя мястото с най-големия 20 } // потомък, освен ако е по-голям от всички потомци 21 22 void heapSort(int *a, int n) // Пирамидално сортиране (tri par tas) 23 { // Сортиращо дърво, heap, tas: пирамида 24 int i, tmp; 25 26 for (i = n / 2; i >= 0; i--) // Създай сортиращо дърво (максималният 27 downHeap(a, i, n); // елемент на масива ще бъде в корена) 28 for (i = n - 1; i > 0; i--) { 29 tmp = a[i]; // Размени местата на максимума 30 a[i] = a[0]; // и последния елемент на масива 31 a[0] = tmp; 32 downHeap(a, 0, i); // Препострой сортиращото дърво за 33 } // неотсортираната част от масива 34 } 35 */ 36 37 .global heapSort //void heapSort(int *a, int n) //R0, R1 38 heapSort: // { | int i, tmp; // R3 (R1), R3 39 { R8 = LR //Съхрани LR, защото „CALL“ ще го промени! 40 R3 = LSR(R1,#1) // | for (i = n / 2; i >= 0; i--) 41 0000 08407F70 2341018C E1FFE1BF R1 = ADD(R1,#-1)}//n-- | 42 L1: { R2 = R3 // i | 43 CALL DOWNHEAP // | downHeap(a, i, n); //R0,R2,R1 44 000c 1640005A 33333230 R3 = ADD(R3,#-1) }// | // i--) 45 0014 FCFF6361 IF (R3>=#0) JUMP:T L1// | // i >= 0; 46 L2: { R4 = MEMW(R0)// | for (i = n - 1; i > 0; i--) {//R1 = i 47 0018 04408091 03E1803A R3 = MEMW(R0+R1<<#2) }// | tmp = a[i]; 48 { MEMW(R0+R1<<#2) = R4// | a[i] = a[0]; 49 0020 0461803B 00C380A1 MEMW(R0) = R3 } // | a[0] = tmp; 50 { R2 = #0 // k = 0 | 51 R1 = ADD(R1,#-1)//i-- (n--) | downHeap(a, 0, i); //R0,R2,R1 52 0028 0840005A 11330228 CALL DOWNHEAP }// ______| } // i > 0; 53 0030 F4FF2161 IF (R1!=#0) JUMP:T L2//__/}void downHeap(int *a, int k,int n)//R0,R2,R1 54 0034 00C08852 JUMPR R8 // { | int i,tmp;/*R4,5*/n--;//вече намалено 55 0038 05E2803A DOWNHEAP: R5 = MEMW(R0+R2<<#2)//_/ | for (tmp = a[k]; k <= n / 2; k = i) { 56 003c 26C1018C L3: R6 = LSR(R1,#1) //n / 2 | 57 { P0 = CMP.GTU(R2,R6)//k <= n / 2 ? 58 IF (P0.NEW) JUMP:NT L5//ако не, край на цикъла 59 0040 16460215 44C1028C R4 = ASL(R2,#1) }// | i = 2 * k; 60 { P0 = CMP.LTU(R4,R1)// | if (i < n 61 0048 08C44115 IF (!P0.NEW) JUMP:NT L4 }// | && 62 004c 06E4C03A R7:6 = MEMD(R0+R4<<#2)// | 63 { P0 = CMP.LT(R6,R7)// | a[i] < a[i+1]) 64 0050 004647F2 24E00474 IF (P0.NEW) R4 = ADD(R4,#1) }// | i++; 65 0058 06E4803A L4: R6 = MEMW(R0+R4<<#2)// | 66 005c 00C546F2 P0 = CMP.LT(R5,R6)// | if (tmp >= a[i]) break; 67 { IF (P0) MEMW(R0+R2<<#2) = R6// | a[k] = a[i]; 68 IF (P0) R2 = R4 // k = i | } 69 0060 02400474 EE60DF5C 06E28034 IF (P0) JUMP L3 } 70 L5: { MEMW(R0+R2<<#2) = R5// | a[k] = tmp; 71 006c 00409F52 05E2803B JUMPR LR } // } S/390 GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .global getvlq 16 getvlq: # src = рег. 2, c = рег. 1, p = рег. 3 17 0000 A758007F LHI 5,0x7F # подготви маска за NR 18 0004 1744 XR 4,4 # value се съставя в рег. 4 19 0006 1711 XR 1,1 # старшите 3 байта трябва да бъдат 0 в началото 20 0008 58302000 L 3,0(2) # получи указателя към потока от данни 21 000c A7F40008 J L2 # премини към получаване на първия байт 22 0010 1415 L1: NR 1,5 # маскирай бит 7, остави значещите битове 0-6 23 0012 1641 OR 4,1 # „сглоби“ най-младшия засега байт 24 0014 89400007 SLL 4,7 # value <<= 7 25 0018 A73A0001 AHI 3,1 # обнови адреса 26 001c BF113000 L2: ICM 1,1,0(3) # получи следващия байт 27 0020 A744FFF8 JM L1 # ако има ли още байтове (бит 7 = 1), продължи 28 0024 A73A0001 AHI 3,1 # укажи към следващите данни 29 0028 50302000 ST 3,0(2) # съхрани указателя 30 002c 41241000 LA 2,0(4,1) # „сглоби“ стойността и я върни в рег. 2 31 0030 07FE0707 BR 14 ==> id32/getvlq.s <== 1 *unsigned getVLQ(unsigned char **src) 2 *{ // read a variable length quantity 3 * unsigned char c, *p = *src; // (see Standard MIDI-File Format Spec. 1.1) 4 * unsigned value = *p++; 5 * if (value & 0x80) { 6 * value &= 0x7f; 7 * do 8 * value = (value << 7) + ((c = *p++) & 0x7f); 9 * while (c & 0x80); 10 * } 11 * *src = p; 12 * return value; 13 *} 14 15 entry getvlq 00000000d 16 getvlq equ * 00000d 5837 0000 17 l 3,0(7) src 00004d 5823 0000 18 l 2,0(3) p 00008d 0700 19 xr 0,0 value will be accumulated in register 0 0000Ad D312 0000 20 L1 lb 1,0(2) get the next byte (register 1 = c) 0000Ed 2621 21 ais 2,1 update the address 00010d 1107 22 slls 0,7 value <<= 7 00012d 0841 23 lr 4,1 replace bits 6-0 of value with the same bits of 00014d C440 007F 24 nhi 4,x'7f'(0) c (mask bit 7 & leave the significant bits 0-6, 00018d 0604 25 or 0,4 "assemble" the lowmost byte so far) 0001Ad C310 0080 26 thi 1,x'80'(0) last byte? 0001Ed 203A 0000000Ad 27 bnzs L1 no, go to the next one 00020d 5023 0000 28 st 2,0(3) yes, save the pointer to the next data 00024d 030F 29 br 15 VAX GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global _getvlq 18 _getvlq: 19 0000 0400 .word 0x4 # R2 20 0002 D0BC0452 MOVL *4(AP),R2 # 4(AP) = src, R1 = c, R2 = p 21 0006 D450 CLRL R0 # value ще се натрупва в R0 22 0008 9A8251 L1: MOVZBL (R2)+,R1 # получи следващия байт и обнови адреса 23 000b 78075050 ASHL $7,R0,R0 # value <<= 7 24 000f F0510007 50 INSV R1,$0,$7,R0 # замени битове 6-0 със съответните битове на c 25 0014 E00751F0 BBS $7,R1,L1 # ако не е последен байт, премини към следващия 26 0018 D052BC04 MOVL R2,*4(AP) # съхрани указателя към следващите данни 27 001c 04010101 RET ==> we32k/getvlq.s <== #unsigned getVLQ(unsigned char **src) #{ // read a variable length quantity # unsigned char c, *p = *src; // (see Standard MIDI-File Format Spec. 1.1) # unsigned value = *p++; # if (value & 0x80) { # value &= 0x7f; # do # value = (value << 7) + ((c = *p++) & 0x7f); # while (c & 0x80); # } # *src = p; # return value; #} section .text .globl getvlq getvlq() getvlq: 0: 84 da 00 42 MOVW *0(%ap),%r2 # 0(ap) = src, r1 = c, r2 = p 4: 70 NOP 5: 80 40 CLRW %r0 # value will be accumulated in r0 7: 87 52 41 L1: MOVB (%r2),%r1 # get the next byte a: 70 NOP b: 90 42 INCW %r2 # update the address d: d0 07 40 40 LLSW3 &7,%r0,%r0 # value <<= 7 11: c8 06 00 41 40 INSFW &6,&0,%r1,%r0 # replace bits 6-0 with the same bits of c 16: 2b 41 TSTB %r1 # last byte? 18: 4b ef BLB L1 # no, go to the next one 1a: 84 42 da 00 MOVW %r2,*0(%ap) # yes, save the pointer to the next data 1e: 70 NOP 1f: 08 RET 68K GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 0000 2077 0161 0004 MOVEL ([4,%SP]),%A0 | 4(SP) = src, D1 = c, A0 = p 20 0006 4280 CLRL %D0 | value ще се натрупва в D0 21 0008 1218 L1: MOVEB (%A0)+,%D1 | получи следващия байт и обнови адреса 22 000a EF88 LSLL #7,%D0 | value <<= 7 23 000c EFC0 1647 BFINS %D1,%D0{25:7} | замени битове 6-0 със съответните битове на c 24 0010 8201 ORB %D1,%D1 | ако това не е последният байт (т.е. ако 25 0012 6BF4 BMIB L1 | бит 7 = лог. 1), премини към следващия 26 0014 2F88 0161 0004 MOVEL %A0,([4,%SP]) | съхрани указателя към следващите данни 27 001a 4E75 RTS x86 NASM getvlq.s 1 ;unsigned getVLQ(unsigned char **src) 2 ;{ // прочети величина с променлива дължина 3 ; unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 ; unsigned value = *p++; 5 ; if (value & 0x80) { 6 ; value &= 0x7f; 7 ; do 8 ; value = (value << 7) + ((c = *p++) & 0x7f); 9 ; while (c & 0x80); 10 ; } 11 ; *src = p; 12 ; return value; 13 ;} 14 15 section .text 16 global getvlq,_getvlq ;в GCC декларирай с __attribute__((regparm(3))) 17 getvlq: 18 _getvlq: 19 00000000 91 XCHG EAX,ECX ; src = ECX, c = AL, p = ESI 20 00000001 31D2 XOR EDX,EDX ; value се съставя в EDX 21 00000003 8731 XCHG ESI,[ECX] ; получи адреса и съхрани ESI на мястото му 22 00000005 AC L1: LODSB ; получи следващия байт и обнови адреса 23 00000006 C1C807 ROR EAX,7 ; битове 31–25 = битове 6–0, бит 0 = бит 7 24 00000009 0FA4C207 SHLD EDX,EAX,7 ; value = value << 7 | c & 0x7f 25 0000000D A801 TEST AL,1 ; има ли още байтове? 26 0000000F 75F4 JNZ L1 ; да, продължи 27 00000011 92 XCHG EAX,EDX ; не, върни стойността в EAX 28 00000012 8731 XCHG ESI,[ECX] ; съхрани новия адрес и възстанови ESI 29 00000014 C3 RET ARM GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 0000 003090E5 LDR R3,[R0] // src = R0, c = R1, p = R3 20 0004 0020A0E3 MOV R2,#0 // value ще се натрупва в R2 21 0008 0110D3E4 L1: LDRB R1,[R3],#1 // получи следващия байт и обнови адреса 22 000c 800051E3 CMP R1,#0x80 // има ли още байтове? 23 0010 7F1001E2 AND R1,R1,#0x7F //(маскирай бит 7, остави значещите битове 0-6 24 0014 822381E1 ORR R2,R1,R2,LSL #7 //value <<= 7, „сглоби“ най-младшия дотук байт) 25 0018 FAFFFF2A BHS L1 // да, продължи 26 001c 003080E5 STR R3,[R0] // не, съхрани указателя към следващите данни 27 0020 0200A0E1 MOV R0,R2 // върни стойността в R0 28 0024 1EFF2FE1 BX LR ARC GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 0000 0443 LD_S r3,[r0] # src = r0, c = r1, p = r3 20 0002 4C70 MOV_S r2,0 # value ще се натрупва в r2 21 0004 0113 8104 L1: LDB.AB r1,[r3,1] # получи следващия байт и обнови адреса 22 0008 576A ASL_S r2,r2,7 # value <<= 7 23 000a 5321 8C01 BMSK r12,r1,6 # маскирай бит 7, остави значещите битове 0-6 24 000e 857A OR_S r2,r2,r12 # „сглоби“ най-младшия дотук байт 25 0010 F509 D781 BBIT1 r1,7,L1 # ако не е последен байт, премини към следващия 26 0014 60A0 ST_S r3,[r0] # не, съхрани указателя към следващите данни 27 0016 4040 MOV_S r0,r2 # върни стойността в r0 28 0018 E07E J_S [blink] PPC GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .global getvlq 16 getvlq: 17 0000 80C30000 lwz r6,0(r3) # src = r3, c = r4, p = r6 18 0004 38A00000 li r5,0 # value ще се натрупва в r5 19 0008 38C6FFFF addi r6,r6,-1 # компенсирай преинкрементната адресация 20 000c 8C860001 L1: lbzu r4,1(r6) # получи следващия байт и обнови адреса 21 0010 28040080 cmplwi r4,0x80 # има ли още байтове? 22 0014 54A53830 slwi r5,r5,7 # (value <<= 7, 23 0018 5085067E rlwimi r5,r4,0,25,31 # „сглоби“ най-младшия дотук байт) 24 001c 4080FFF0 bge L1 # да, продължи 25 0020 38C60001 addi r6,r6,1 # не, укажи към следващия байт 26 0024 90C30000 stw r6,0(r3) # съхрани указателя към следващите данни 27 0028 7CA32B78 mr r3,r5 # върни стойността в r3 28 002c 4E800020 blr SPARC GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 0000 D4020000 ld [%o0],%o2 ! src = %o0, c = %o1, p = %o2 20 0004 96100000 clr %o3 ! value ще се натрупва в %o3 21 0008 D20A8000 L1: ldub [%o2],%o1 ! получи следващия байт 22 000c 80A26080 cmp %o1,0x80 ! има ли още байтове? 23 0010 920A607F and %o1,0x7F,%o1 ! (маскирай бит 7, остави значещите битове 0-6 24 0014 972AE007 sll %o3,7,%o3 ! value <<= 7, 25 0018 9612C009 or %o3,%o1,%o3 ! „сглоби“ най-младшия дотук байт) 26 001c 1ABFFFFB bcc L1 ! да, продължи (изпълнява се след „inc“!) 27 0020 9402A001 inc %o2 ! обнови адреса 28 0024 D4220000 st %o2,[%o0] ! не, съхрани указателя към следващите данни 29 0028 81C3E008 retl ! изпълнява се след „mov“! 30 002c 9010000B mov %o3,%o0 ! върни стойността в %o0 MIPS GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .ent getvlq 16 .global getvlq 17 getvlq: 18 0000 8C860000 LW $6,0($4) # src = $4, c = $5, p = $6 19 0004 24020000 LI $2,0 # value ще се натрупва в $2 20 0008 80C50000 L1: LB $5,0($6) # получи следващия байт и разшири знака 21 000c 24C60001 ADDIU $6,$6,1 # обнови адреса 22 0010 000211C0 SLL $2,$2,7 # value <<= 7 23 INS $2,$5,0,7 # „сглоби“ най-младшия дотук байт 24 0014 04A0FFFC 7CA23004 BLTZ $5,L1 # ако има още байтове, премини към следващия 25 SW $6,0($4) # съхрани указателя към следващите данни 26 001c 03E00008 AC860000 JR $31 # върни стойността в $2 27 0024 00000000 00000000 00000000 .end getvlq RISC-V GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .global getvlq 16 getvlq: 17 0000 1041 LW a2,0(a0) # src = a0, c = a1, p = a2 18 0002 8146 LI a3,0 # value ще се натрупва в a3 19 0004 83050600 L1: LB a1,0(a2) # получи следващия байт и разшири знака 20 0008 0506 ADDI a2,a2,1 # обнови адреса 21 000a 13F7F507 ANDI a4,a1,0x7F # маскирай бит 7, остави значещите битове 0-6 22 000e 9E06 SLLI a3,a3,7 # value <<= 7 23 0010 D98E OR a3,a3,a4 # „сглоби“ най-младшия дотук байт 24 0012 E3C905FE BLTZ a1,L1 # ако има още байтове, премини към следващия 25 0016 10C1 SW a2,0(a0) # съхрани указателя към следващите данни 26 0018 3685 MV a0,a3 # върни стойността в a0 27 001a 8280 RET Nios II GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .global getvlq 16 getvlq: 17 0000 17008021 LDW r6,(r4) # src = r4, c = r5, p = r6 18 0004 14008000 MOVUI r2,0 # value ще се натрупва в r2 19 0008 07004031 L1: LDB r5,(r6) # получи следващия байт и разшири знака 20 000c 44008031 ADDI r6,r6,1 # обнови адреса 21 0010 CC1F002A ANDI r8,r5,0x7F # маскирай бит 7, остави значещите битове 0-6 22 0014 FA910410 SLLI r2,r2,7 # value <<= 7 23 0018 3AB00412 OR r2,r2,r8 # „сглоби“ най-младшия дотук байт 24 001c 16FA3F28 BLT r5,r0,L1 # ако има още байтове, премини към следващия 25 0020 15008021 STW r6,(r4) # съхрани указателя към следващите данни 26 0024 3A2800F8 RET # върни стойността в r2 Xtensa GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .global getvlq 16 getvlq: 17 0000 4802 L32I a4,a2,0 # src = a2, c = a3, p = a4 18 0002 0C05 MOVI a5,0 # value ще се натрупва в a5 19 0004 320400 L1: L8UI a3,a4,0 # получи следващия байт 20 0007 1B44 ADDI a4,a4,1 # обнови адреса 21 0009 306064 EXTUI a6,a3,0,7 # маскирай бит 7, остави значещите битове 0-6 22 000c 905511 SLLI a5,a5,7 # value <<= 7 23 000f 605520 OR a5,a5,a6 # „сглоби“ най-младшия дотук байт 24 0012 77E3EE BBSI a3,7,L1 # ако има още байтове, премини към следващия 25 0015 4902 S32I a4,a2,0 # съхрани указателя към следващите данни 26 0017 2D05 MOV a2,a5 # върни стойността в a2 27 0019 0DF0 RET 88K GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global _getvlq 18 0000 F4821400 _getvlq: 19 0004 F4A05800 ld r4,r2,r0 # src = r2, c = r3, p = r4 20 0008 F4640C00 or r5,r0,r0 # value ще се натрупва в r5 21 000c 60840001 L1: ld.bu r3,r4,r0 # получи следващия байт 22 0010 48C3007F addu r4,r4,1 # обнови адреса 23 0014 F0A5A007 mask r6,r3,0x7F # маскирай бит 7, остави значещите битове 0-6 24 0018 F4A65805 mak r5,r5,0<7> # value <<= 7 25 001c D8E3FFFB or r5,r6,r5 # „сглоби“ най-младшия дотук байт 26 0020 F4822400 bb1 7,r3,L1 # ако има още байтове, продължи 27 0024 F4455800 st r4,r2,r0 # съхрани указателя към следващите данни 28 0028 F400C001 or r2,r5,r0 # върни стойността в r2 jmp r1 Or1k GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 0000 84A30000 L.LWZ R5,0(R3) # src = R3, c = R4, p = R5 20 0004 E1600004 L.OR R11,R0,R0 # value ще се натрупва в R11 21 0008 8C850000 L1: L.LBZ R4,0(R5) # получи следващия байт 22 000c BC640080 L.SFGEUI R4,0x80 # има ли още байтове? 23 0010 A484007F L.ANDI R4,R4,0x7F # (маскирай бит 7, остави значещите битове 0-6 24 0014 B96B0007 L.SLLI R11,R11,7 # value <<= 7, 25 0018 E16B2004 L.OR R11,R11,R4 # „сглоби“ най-младшия дотук байт) 26 001c 13FFFFFB L.BF L1 # да, продължи (изпълнява се след „L.ADDI“!) 27 0020 9CA50001 L.ADDI R5,R5,1 # (обнови адреса) 28 0024 44004800 L.JR LR # не, върни управлението; изп. се преди „L.SW“! 29 0028 D4032800 L.SW 0(R3),R5 # (съхрани указателя към следващите данни) Xilinx MicroBlaze GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .global getvlq 16 getvlq: 17 0000 0000E5E8 LWI R7,R5,0 # src = R5, c = R6, p = R7 18 0004 00006080 OR R3,R0,R0 # value ще се натрупва в R3 19 0008 0000C7E0 L1: LBUI R6,R7,0 # получи следващия байт 20 000c 0100E720 ADDI R7,R7,1 # обнови адреса 21 0010 800006A5 ANDI R8,R6,0x80 # има ли още байтове? 22 0014 7F00C6A4 ANDI R6,R6,0x7F # (маскирай бит 7, остави значещите битове 0-6, 23 0018 07046364 BSLLI R3,R3,7 # value <<= 7, 24 001c 00306380 OR R3,R3,R6 # „сглоби“ най-младшия дотук байт) 25 0020 E8FF28BC BNEI R8,L1 # да, продължи 26 0024 08000FB6 RTSD R15,8 # върни стойността в R3 (изпълн.се след „SWI“!) 27 0028 0000E5F8 SWI R7,R5,0 # съхрани указателя към следващите данни HPPA GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 .text 17 .global getvlq 18 getvlq: 19 0000 0F401098 LDW 0(%R26),%R24 ; %R26 = src, %R25 = c, %R24 = p 20 0004 341C0000 LDI 0,%R28 ; value ще се натрупва в %R28 21 0008 0F021039 L1: LDBS,MA 1(%R24),%R25 ; Получи следващия байт и обнови адреса 22 000c D39C08DC SHD %R28,%R28,25,%R28; value <<= 7 23 0010 C7195FE5 BB,< %R25,24,L1 ; Има още байтове? (Изпълнява се след „DEP“!) 24 0014 D7990C19 DEP %R25,31,7,%R28 ; Замени битове 6-0 със съответните битове на c 25 0018 0F581280 STW %R24,0(%R26) ; Съхрани указателя към следващите данни 26 001c E840C002 BV,N (%R2) Renesas / SuperH SH GAS Little Endian getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 0000 4262 MOV.L @R4,R2 ! src = R4, c = R0, p = R2 20 0002 00E1 MOV #0,R1 ! value ще се натрупва в R1 21 0004 07E3 MOV #7,R3 ! брой двоични разреди за изместване 22 0006 2460 L1: MOV.B @R2+,R0 ! получи следващия байт и обнови адреса 23 0008 80C8 TST #0x80,R0 ! има ли още байтове? 24 000a 7FC9 AND #0x7F,R0 ! (маскирай бит 7, остави значещите битове 0-6 25 000c 3D41 SHLD R3,R1 ! value <<= 7, 26 000e 0B21 OR R0,R1 ! „сглоби“ най-младшия дотук байт) 27 0010 F98B BF L1 ! да, продължи 28 0012 2224 MOV.L R2,@R4 ! не, съхрани указателя към следващите данни 29 0014 0B00 RTS ! върни управлението (изпълнява се след „MOV“!) 30 0016 1360 MOV R1,R0 ! R0 = value GAS for CRIS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 0000 6ACA MOVE.D [$R10],$R12 ; src = R10, c = R11, p = R12 20 0002 7D86 CLEAR.D $R13 ; value ще се натрупва в R13 21 0004 4CBC L1: MOVU.B [$R12+],$R11 ; получи следващия байт 22 0006 CFBC8000 CMPU.B 0x80,$R11 ; има ли още байтове? 23 000a 0FBF7F00 AND.B 0x7F,$R11 ; (маскирай бит 7, остави значещите битове 0-6 24 000e C7D3 LSLQ 7,$R13 ; value <<= 7) 25 0010 F500 BHS L1 ; да, продължи (изпълнява се след „OR“!) 26 0012 6BD7 OR.D $R11,$R13 ; „сглоби“ най-младшия дотук байт 27 0014 EACB MOVE.D $R12,[$R10] ; не, съхрани указателя към следващите данни 28 0016 F0B9 RET ; изпълнява се след „MOVE“! 29 0018 6DA60000 MOVE.D $R13,$R10 ; върни стойността в $R10 BFIN GAS getvlq.s page 1 1 #unsigned getVLQ(unsigned char **src) 2 #{ // прочети величина с променлива дължина 3 # unsigned char c, *p = *src;// (вж. Standard MIDI-File Format Spec. 1.1) 4 # unsigned value = *p++; 5 # if (value & 0x80) { 6 # value &= 0x7f; 7 # do 8 # value = (value << 7) + ((c = *p++) & 0x7f); 9 # while (c & 0x80); 10 # } 11 # *src = p; 12 # return value; 13 #} 14 15 .global _getvlq 16 _getvlq: 17 0000 0032 P0 = R0; # src = R0 -> P0 18 0002 4191 P1 = [P0]; # c = R1, p = P1 19 0004 0058 R0 = R0 ^ R0; # value ще се натрупва в R0 20 0006 0998 L_1: R1 = B [P1++] (Z); # получи следващия байт 21 0008 3949 CC = BITTST (R1, 7); 22 000a 394C BITCLR (R1, 7); # маскирай бит 7, остави значещите битове 0-6 23 000c 384F R0 <<= 7; # освободи младшите 7 бита 24 000e 0856 R0 = R0 | R1; # „сглоби“ най-младшия дотук байт 25 0010 FB1B IF CC JUMP L_1; # ако има още байтове, премини към следващия 26 0012 4193 [P0] = P1; # съхрани указателя към следващите данни 27 0014 10000000 RTS; # върни стойността в R0 Hexagon GAS getvlq.s page 1 1 /* 2 unsigned getVLQ(unsigned char **src) 3 { // прочети величина с променлива дължина 4 unsigned char c, *p = *src; // (вж. Standard MIDI-File Format Spec. 1.1) 5 unsigned value = *p++; 6 if (value & 0x80) { 7 value &= 0x7f; 8 do 9 value = (value << 7) + ((c = *p++) & 0x7f); 10 while (c & 0x80); 11 } 12 *src = p; 13 return value; 14 } 15 */ 16 17 .global getvlq 18 getvlq: 19 { R3 = MEMW(R0) // src = R0, c = R1, p = R3 20 0000 03000248 R2 = #0 } // value ще се натрупва в R2 21 0004 21C0039B L1: R1 = MEMB(R3++#1) //получи нов байт, разшири знака, обнови адреса 22 0008 E4CF0176 R4 = AND(R1,#0x7F) // маскирай бит 7, остави значещите битове 0-6 23 { R2 = ADDASL(R4,R2,#7)// value <<= 7, „сглоби“ най-младшия дотук байт 24 P0 = CMP.GE(R1,#0) 25 000c E24402C4 FC78FF5C E0FF6175 IF (!P0.NEW) JUMP:T L1 }// ако има още байтове, продължи 26 { MEMW(R0) = R3 // ако няма, съхрани указателя към следващите 27 R0 = R2 // данни и върни стойността в R0 28 0018 00409F52 03002070 JUMPR LR } S/390 GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global putvlq 19 putvlq: 20 0000 A708007F LHI 0,0x7F #//value се предава в рег. 2, dest - в рег. 3 21 0004 A7180080 LHI 1,0x80 #//подготви маски за NR и OR 22 0008 1842 LR 4,2 # buffer = value 23 000a 1440 NR 4,0 # & 0x7f; 24 000c 8A200007 L1: SRA 2,7 # while ((value >>= 7) > 0)//value e 28 бита 25 0010 A784000A JZ L2 # { 26 0014 89400008 SLL 4,8 # buffer <<= 8; 27 0018 1641 OR 4,1 # buffer |= 0x80; 28 001a 1852 LR 5,2 # value 29 001c 1450 NR 5,0 # & 0x7f; 30 001e 1E45 ALR 4,5 # buffer += 31 0020 A7F4FFF6 J L1 # } for ( ; ; ) { 32 0024 42403000 L2: STC 4,0(3) # *dest = (unsigned char)buffer; 33 0028 A73A0001 AHI 3,1 # ++ 34 002c A7410080 TML 4,0x80 # if (buffer & 0x80) 35 0030 A7840006 JZ L3 # { 36 0034 88400008 SRL 4,8 # buffer >>= 8; 37 0038 A7F4FFF6 J L2 # } 38 003c 1823 L3: LR 2,3 # else return dest; 39 003e 07FE BR 14 # } ==> id32/putvlq.s <== 1 *unsigned char *putVLQ(unsigned value, unsigned char *dest) // write a VLQ 2 *{ // (see Standard MIDI-File Format Spec. 1.1) 3 * unsigned buffer = value & 0x7f; 4 * while ((value >>= 7) > 0) { 5 * buffer <<= 8; 6 * buffer |= 0x80; 7 * buffer += value & 0x7f; 8 * } 9 * for ( ; ; ) { 10 * *dest++ = (unsigned char)buffer; 11 * if (buffer & 0x80) 12 * buffer >>= 8; 13 * else 14 * return dest; 15 * } 16 *} 17 18 entry putvlq 00000000d 19 putvlq equ * //Registers: 0 = value, 1 = dest, 2 = buffer 00000d 5807 0000 20 l 0,0(7) putVLQ(unsigned value, unsigned char *dest) 00004d 5817 0004 21 l 1,4(7) { 00008d 0820 22 lr 2,0 unsigned buffer = value 0000Ad C420 007F 23 nhi 2,x'7f'(0) & 0x7f; 0000Ed 1007 24 L1 srls 0,7 while ((value >>= 7) 00010d 2339 00000022d 25 bzs L2 > 0) { 00012d 1128 26 slls 2,8 buffer <<= 8; 00014d C620 0080 27 ohi 2,x'80'(0) buffer |= 0x80; 00018d 0830 28 lr 3,0 value 0001Ad C430 007F 29 nhi 3,x'7f'(0) & 0x7f; 0001Ed 0A23 30 ar 2,3 buffer += 00020d 2209 0000000Ed 31 bs L1 } for ( ; ; ) { 00022d D221 0000 32 L2 stb 2,0(1) *dest++ = (unsigned char)buffer; 00026d 2611 33 ais 1,1 //++ 00028d C320 0080 34 thi 2,x'80'(0) 0002Cd 2333 00000032d 35 bzs L3 __ if (buffer & 0x80) 0002Ed 1028 36 srls 2,8 \ buffer >>= 8; 00030d 2207 00000022d 37 bs L2 \___ else return dest; 00032d 0801 38 L3 lr 0,1 } 00034d 030F 39 br 15 }//Return the pointer to the next byte in reg.0 VAX GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global _putvlq 19 _putvlq: #R0 = value, R1 = dest, R2 = buffer 20 0000 0400 .word 0x4 #R2 21 0002 7DAC0450 MOVQ 4(AP),R0 #putVLQ(unsigned value, unsigned char *dest) { 22 0006 CB8F80FF FFFF5052 BICL3 $-0x80,R0,R2 # unsigned buffer = value & 0x7f; 23 000e EF071950 50 L1: EXTZV $7,$25,R0,R0 # while ((value >>= 7) > 0) { 24 0013 130F BEQL L2 25 0015 78085252 ASHL $8,R2,R2 # buffer <<= 8; 26 0019 888F8052 BISB2 $0x80,R2 # buffer |= 0x80; 27 001d F0500007 52 INSV R0,$0,$7,R2 # buffer += value & 0x7f; } 28 0022 11EA BRB L1 # for ( ; ; ) { 29 0024 905281 L2: MOVB R2,(R1)+ # *dest++ = (unsigned char)buffer; 30 0027 E1075207 BBC $7,R2,L3 #__ if (buffer & 0x80) 31 002b EF081852 52 EXTZV $8,$24,R2,R2 # \ buffer >>= 8; 32 0030 11F2 BRB L2 # \___ else return dest; 33 0032 D05150 L3: MOVL R1,R0 # } 34 0035 040101 RET #} //Върни указателя към следващия байт в R0 ==> we32k/putvlq.s <== #unsigned char *putVLQ(unsigned value, unsigned char *dest) // write a VLQ #{ // (see Standard MIDI-File Format Spec. 1.1) # unsigned buffer = value & 0x7f; # while ((value >>= 7) > 0) { # buffer <<= 8; # buffer |= 0x80; # buffer += value & 0x7f; # } # for ( ; ; ) { # *dest++ = (unsigned char)buffer; # if (buffer & 0x80) # buffer >>= 8; # else # return dest; # } #} section .text .globl putvlq putvlq() putvlq: #//r0 = value, r1 = dest, r2 = buffer 0: 84 5a 40 MOVW 0(%ap),%r0 #putVLQ(unsigned value, unsigned char *dest) 3: 84 74 41 MOVW 4(%ap),%r1 #{ 6: f8 6f 7f 40 42 ANDW3 &0x7F,%r0,%r2 # unsigned buffer = value & 0x7f; b: d4 07 40 40 L1: LRSW3 &7,%r0,%r0 # while ((value >>= 7) > 0) { f: 7f 12 BEB L2 11: d0 08 42 42 LLSW3 &8,%r2,%r2 # buffer <<= 8; 15: b0 5f 80 00 42 ORW2 &0x80,%r2 # buffer |= 0x80; 1a: c8 06 00 40 42 INSFW &6,&0,%r0,%r2 # buffer += value & 0x7f; 1f: 7b ec BRB L1 # } for ( ; ; ) { 21: 87 42 51 L2: MOVB %r2,(%r1) # *dest++ = (unsigned char)buffer; 24: 70 NOP 25: 90 41 INCW %r1 #//++ 27: 2b 42 TSTB %r2 29: 43 08 BGEB L3 #__ if (buffer & 0x80) 2b: d4 08 42 42 LRSW3 &8,%r2,%r2 # \ buffer >>= 8; 2f: 7b f2 BRB L2 # \___ else return dest; 31: 84 41 40 L3: MOVW %r1,%r0 # } 34: 08 RET #} //Return the pointer to the next byte in r0 35: 70 NOP 36: 70 NOP 37: 70 NOP 68K GAS putvlq.s page 1 1 |unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 |{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 | unsigned buffer = value & 0x7f; 4 | while ((value >>= 7) > 0) { 5 | buffer <<= 8; 6 | buffer |= 0x80; 7 | buffer += value & 0x7f; 8 | } 9 | for ( ; ; ) { 10 | *dest++ = (unsigned char)buffer; 11 | if (buffer & 0x80) 12 | buffer >>= 8; 13 | else 14 | return dest; 15 | } 16 |} 17 18 .global putvlq 19 putvlq: |D0 = value, A0 = dest, D1 = buffer 20 0000 4CEF 0101 0004 MOVEML 4(%SP),%D0/%A0 |putVLQ(unsigned value, unsigned char *dest) { 21 0006 E9C0 1647 BFEXTU %D0{25:7},%D1 | unsigned buffer = value & 0x7f; 22 000a EE88 L1: LSRL #7,%D0 | while ((value >>= 7) > 0) { 23 000c 670C BEQB L2 24 000e E189 LSLL #8,%D1 | buffer <<= 8; 25 0010 0001 0080 ORIB #0x80,%D1 | buffer |= 0x80; 26 0014 EFC1 0647 BFINS %D0,%D1{25:7} | buffer += value & 0x7f; 27 0018 60F0 BRAB L1 | } for ( ; ; ) { 28 001a 10C1 L2: MOVEB %D1,(%A0)+ | *dest++ = (unsigned char)buffer; 29 001c E089 LSRL #8,%D1 | if (buffer & 0x80) buffer >>= 8; 30 001e 65FA BCSB L2 | else return dest; 31 0020 2008 L3: MOVEL %A0,%D0 | } 32 0022 4E75 RTS |} //Върни указателя към следващия байт в D0 x86 NASM putvlq.s 1 ;unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 ;{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 ; unsigned buffer = value & 0x7f; 4 ; while ((value >>= 7) > 0) { 5 ; buffer <<= 8; 6 ; buffer |= 0x80; 7 ; buffer += value & 0x7f; 8 ; } 9 ; for ( ; ; ) { 10 ; *dest++ = (unsigned char)buffer; 11 ; if (buffer & 0x80) 12 ; buffer >>= 8; 13 ; else 14 ; return dest; 15 ; } 16 ;} 17 18 section .text 19 global putvlq,_putvlq 20 putvlq: ;void __attribute__((regparm(3))) putvlq(...) { 21 _putvlq: ;//value се предава в EAX, dest - в EDX 22 00000000 89C1 MOV ECX,EAX ;//buffer е удобно да бъде в EAX заради STOSB 23 00000002 87D7 XCHG EDX,EDI ;//съхрани EDI, STOSB изисква dest да е в EDI 24 00000004 83E07F AND EAX,7FH ; buffer = value & 0x7f; 25 00000007 C1E907 L1: SHR ECX,7 ; while ((value >>= 7) > 0) 26 0000000A 7409 JZ L2 ; { 27 0000000C C1E008 SHL EAX,8 ; buffer <<= 8; 28 0000000F 0C80 OR AL,80H ; buffer |= 0x80; 29 00000011 08C8 OR AL,CL ; buffer |= value & 0xFF; 30 00000013 EBF2 JMP L1 ; } for ( ; ; ) { 31 00000015 AA L2: STOSB ; *dest++ = (unsigned char)buffer; 32 00000016 C1E808 SHR EAX,8 ;___ ___ if (buffer & 0x80) 33 00000019 72FA JC L2 ;___X___ buffer >>= 8; 34 0000001B 97 L3: XCHG EAX,EDI ; else return dest; 35 0000001C 89D7 MOV EDI,EDX ; } 36 0000001E C3 RET ;} ARM GAS putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global putvlq // Регистри: value = R0, dest = R1, buffer = R2 21 putvlq: //putVLQ(unsigned value, unsigned char *dest) { 22 0000 7F2000E2 AND R2,R0,#0x7F // unsigned buffer = value & 0x7f; 23 0004 A003B0E1 L1: MOVS R0,R0,LSR #7 // while ((value >>= 7) > 0) { 24 0008 0224A011 MOVNE R2,R2,LSL #8 // buffer <<= 8; 25 000c 80208213 ORRNE R2,R2,#0x80 // buffer |= 0x80; 26 0010 7F300012 ANDNE R3,R0,#0x7F // buffer += value & 0x7f; 27 0014 03208210 ADDNE R2,R2,R3 // _} 28 0018 F9FFFF1A BNE L1 //__/ for ( ; ; ) { 29 001c 0120C1E4 L2: STRB R2,[R1],#1 // *dest++ = (unsigned char)buffer; 30 0020 2224B0E1 MOVS R2,R2,LSR #8 // if (buffer & 0x80) buffer >>= 8; 31 0024 FCFFFF2A BCS L2 // else return dest; 32 0028 0100A0E1 MOV R0,R1 // } 33 002c 1EFF2FE1 BX LR //} ARC GAS putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global putvlq # Регистри: value = r0, dest = r1, buffer = r2 21 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 22 0000 5320 8201 BMSK r2,r0,6 # unsigned buffer = value & 0x7f; 23 0004 4128 C081 L1: LSR.F r0,r0,7 # while ((value >>= 7) > 0) { 24 0008 C02A 2202 ASL.NZ r2,r2,8 # buffer <<= 8; 25 000c CF22 E201 BSET.NZ r2,r2,7 # buffer |= 0x80; 26 0010 5320 8301 BMSK r3,r0,6 # buffer += value & 0x7f; 27 0014 C022 C200 ADD.NZ r2,r2,r3# _} 28 0018 F6F5 BNE_S L1 #__/ for ( ; ; ) { 29 001a 0119 9200 L2: STB.AB r2,[r1,1]# *dest++ = (unsigned char)buffer; 30 001e 412A 0282 LSR.F r2,r2,8 # if (buffer & 0x80) buffer >>= 8; 31 0022 BDF7 BLO_S L2 # else return dest; 32 0024 2040 MOV_S r0,r1 # } 33 0026 E07E J_S [blink] #} PPC GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global putvlq #//Регистри: value = r3, dest = r4, buffer = r5 19 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 20 0000 7065007F andi. r5,r3,0x7F # unsigned buffer = value & 0x7f; 21 0004 5463C9FF L1: srwi. r3,r3,7 # while ((value >>= 7) > 0) { 22 0008 41820014 beq L2 23 000c 54A5402E slwi r5,r5,8 # buffer <<= 8; 24 0010 60A50080 ori r5,r5,0x80 # buffer |= 0x80; 25 0014 5065067E rlwimi r5,r3,0,25,31 # buffer += value & 0x7f; 26 0018 4BFFFFEC b L1 # } 27 001c 3884FFFF L2: addi r4,r4,-1#компенс. for ( ; ; ) { 28 0020 9CA40001 L3: stbu r5,1(r4) # *dest++ = (unsigned char)buffer; 29 0024 70A60080 andi. r6,r5,0x80 # if (buffer & 0x80) 30 0028 4182000C beq L4 #__ 31 002c 54A5C23E srwi r5,r5,8 # \ buffer >>= 8; 32 0030 4BFFFFF0 b L3 # \___ else return dest; 33 0034 38640001 L4: addi r3,r4,1 #++ } 34 0038 4E800020 blr #} SPARC GAS putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global putvlq !//Рег.: value = %o0, dest = %o1, buffer = %o2 21 putvlq: !putVLQ(unsigned value, unsigned char *dest) { 22 0000 940A207F and %o0,0x7F,%o2 ! unsigned buffer = value & 0x7f; 23 0004 91322007 L1: srl %o0,7,%o0 ! while ((value >>= 7) > 0) { 24 0008 80920000 tst %o0 25 000c 02800007 be L2 26 0010 01000000 nop 27 0014 952AA008 sll %o2,8,%o2 ! buffer <<= 8; 28 0018 9412A080 or %o2,0x80,%o2 ! buffer |= 0x80; 29 001c 960A207F and %o0,0x7F,%o3 ! buffer += value & 0x7f; 30 0020 10BFFFF9 ba L1! изпълнява се след „add“ 31 0024 9402800B add %o2,%o3,%o2 32 0028 D42A4000 L2: stb %o2,[%o1] !___ } for ( ; ; ) { 33 002c 92026001 inc %o1 !++ \___ *dest++ = (unsigned char)buffer; 34 0030 808AA080 andcc %o2,0x80,%g0 !___ 35 0034 02800004 be L3 !__ \___ if (buffer & 0x80) 36 0038 01000000 nop ! \ 37 003c 10BFFFFB ba L2! изпълнява се след „srl“ 38 0040 9532A008 srl %o2,8,%o2 ! \ buffer >>= 8; 39 0044 81C3E008 L3: retl ! \_ else return dest; 40 0048 90100009 mov %o1,%o0! изпълнява се преди „retl“ MIPS GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .ent putvlq 19 .global putvlq #//Регистри: value = $4, dest = $5, buffer = $6 20 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 21 0000 3086007F ANDI $6,$4,0x7F # unsigned buffer = value & 0x7f; 22 0004 000421C2 L1: SRL $4,$4,7 # while ((value >>= 7) > 0) { 23 0008 10800005 00000000 BEQ $4,$0,L2 24 0010 00063200 SLL $6,$6,8 # buffer <<= 8; 25 0014 34C60080 ORI $6,$6,0x80 # buffer |= 0x80; 26 INS $6,$4,0,7 # buffer += value & 0x7f; 27 0018 1000FFFA 7C863004 B L1 # } 28 0020 A0A60000 L2: SB $6,0($5) #___ for ( ; ; ) { 29 0024 24A50001 ADDIU $5,$5,1 #++ \___ *dest++ = (unsigned char)buffer; 30 0028 30C70080 ANDI $7,$6,0x80 # if (buffer & 0x80) 31 002c 10E00003 00000000 BEQ $7,$0,L3 #__ 32 SRL $6,$6,8 # \ buffer >>= 8; 33 0034 1000FFFA 00063202 B L2 # \___ else return dest; 34 L3: MOVE $2,$5 # } 35 003c 03E00008 00A01021 JR $31 #} //Върни указателя към следващия байт в $2 36 0044 00000000 00000000 00000000 .end putvlq RISC-V GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global putvlq #//Регистри: value = a0, dest = a1, buffer = a2 19 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 20 0000 1376F507 ANDI a2,a0,0x7F # unsigned buffer = value & 0x7f; 21 0004 1D81 L1: SRLI a0,a0,7 # while ((value >>= 7) > 0) { 22 0006 01C9 BEQZ a0,L2 23 0008 2206 SLLI a2,a2,8 # buffer <<= 8; 24 000a 13660608 ORI a2,a2,0x80 # buffer |= 0x80; 25 000e 9376F507 ANDI a3,a0,0x7F # buffer += value & 0x7f; 26 0012 3696 ADD a2,a2,a3 27 0014 C5BF J L1 # } 28 0016 2380C500 L2: SB a2,0(a1) #___ for ( ; ; ) { 29 001a 8505 ADDI a1,a1,1 #++ \___ *dest++ = (unsigned char)buffer; 30 001c 93760608 ANDI a3,a2,0x80 # if (buffer & 0x80) 31 0020 99C2 BEQZ a3,L3 #__ 32 0022 2182 SRLI a2,a2,8 # \ buffer >>= 8; 33 0024 CDBF J L2 # \___ else return dest; 34 0026 2E85 L3: MV a0,a1 # } 35 0028 8280 RET #} //Върни указателя към следващия байт в a0 Nios II GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global putvlq #//Регистри: value = r4, dest = r5, buffer = r6 19 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 20 0000 CC1F8021 ANDI r6,r4,0x7F # unsigned buffer = value & 0x7f; 21 0004 FAD10820 L1: SRLI r4,r4,7 # while ((value >>= 7) > 0) { 22 0008 26050020 BEQ r4,r0,L2 23 000c 3A920C30 SLLI r6,r6,8 # buffer <<= 8; 24 0010 14208031 ORI r6,r6,0x80 # buffer |= 0x80; 25 0014 CC1FC021 ANDI r7,r4,0x7F # buffer += value & 0x7f; 26 0018 3A88CD31 ADD r6,r6,r7 27 001c 06F93F00 BR L1 # } 28 0020 05008029 L2: STB r6,(r5) #___ for ( ; ; ) { 29 0024 44004029 ADDI r5,r5,1 #++ \___ *dest++ = (unsigned char)buffer; 30 0028 0C20C031 ANDI r7,r6,0x80 # if (buffer & 0x80) 31 002c 26020038 BEQ r7,r0,L3 #__ 32 0030 3AD20C30 SRLI r6,r6,8 # \ buffer >>= 8; 33 0034 06FA3F00 BR L2 # \___ else return dest; 34 0038 3A880528 L3: MOV r2,r5 # } 35 003c 3A2800F8 RET #} //Върни указателя към следващия байт в r2 Xtensa GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global putvlq #//Регистри: value = a2, dest = a3, buffer = a4 19 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 20 0000 204064 EXTUI a4,a2,0,7 # unsigned buffer = value & 0x7f; 21 0003 202741 L1: SRLI a2,a2,7 # while ((value >>= 7) > 0) { 22 0006 8CF2 BEQZ a2,L2 23 0008 804411 SLLI a4,a4,8 # buffer <<= 8; 24 000b 52A080 MOVI a5,0x80 25 000e 504420 OR a4,a4,a5 # buffer |= 0x80; 26 0011 205064 EXTUI a5,a2,0,7 27 0014 5A44 ADD a4,a4,a5 # buffer += value & 0x7f; 28 0016 46FAFF J L1 # } 29 0019 424300 L2: S8I a4,a3,0 #___ for ( ; ; ) { 30 001c 1B33 ADDI a3,a3,1 #++ \___ *dest++ = (unsigned char)buffer; 31 001e 776406 BBCI a4,7,L3 #__ if (buffer & 0x80) 32 0021 404841 SRLI a4,a4,8 # \ buffer >>= 8; 33 0024 46FCFF00 J L2 # \___ else return dest; 34 0028 2D03 L3: MOV a2,a3 # } 35 002a 0DF0 RET #} //Върни указателя към следващия байт в a2 88K GAS putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global _putvlq #//Рег.: value = r2, dest = r3, buffer = r4 21 0000 4882007F _putvlq: #putVLQ(unsigned value, unsigned char *dest) { 22 0004 F0429807 mask r4,r2,0x7F # unsigned buffer = value & 0x7f; 23 0008 E8420006 L1: extu r2,r2,0<7> # while ((value >>= 7) > 0) { 24 000c F084A008 bcnd eq0,r2,L2 25 0010 58840080 mak r4,r4,0<8> # buffer <<= 8; 26 0014 48A2007F or r4,r4,0x80 # buffer |= 0x80; 27 0018 F4846005 mask r5,r2,0x7F # buffer += value & 0x7f; 28 001c C3FFFFFA addu r4,r4,r5 29 0020 F4832C00 br L1 # } 30 0024 60630001 L2: st.b r4,r3,r0 #___ for ( ; ; ) { 31 0028 D0E40003 addu r3,r3,1 #++ \___ *dest++ = (unsigned char)buffer; 32 002c F0849808 bb0 7,r4,L3 #__ if (buffer & 0x80) 33 0030 C3FFFFFC extu r4,r4,0<8> # \ buffer >>= 8; 34 0034 F4435800 br L2 # \___ else return dest; 35 0038 F400C001 L3: or r2,r3,r0 jmp r1 Or1k GAS putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global putvlq #//Рег.: value = R3, dest = R4, buffer = R5 21 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 22 0000 A4A3007F L.ANDI R5,R3,0x7F # unsigned buffer = value & 0x7f; 23 0004 B8630047 L1: L.SRLI R3,R3,7 # while ((value >>= 7) > 0) { 24 0008 E4030000 L.SFEQ R3,R0 25 000c 10000007 L.BF L2 26 0010 15000000 L.NOP 0 27 0014 B8A50008 L.SLLI R5,R5,8 # buffer <<= 8; 28 0018 A8A50080 L.ORI R5,R5,0x80 # buffer |= 0x80; 29 001c A4C3007F L.ANDI R6,R3,0x7F # buffer += value & 0x7f; 30 0020 03FFFFF9 L.J L1# изпълнява се след „L.ADD“! 31 0024 E0A53000 L.ADD R5,R5,R6 32 0028 D8042800 L2: L.SB 0(R4),R5 #___ } for ( ; ; ) { 33 002c 9C840001 L.ADDI R4,R4,1 #++ \___ *dest++ = (unsigned char)buffer; 34 0030 BC650080 L.SFGEUI R5,0x80 #___ 35 0034 0C000004 L.BNF L3 #__ \___ if (buffer & 0x80) 36 0038 15000000 L.NOP 0 # \ 37 003c 03FFFFFB L.J L2# изпълнява се след „L.SRLI“! 38 0040 B8A50048 L.SRLI R5,R5,8 # \ buffer >>= 8; 39 0044 44004800 L3: L.JR LR # \_ else return dest; 40 0048 E1640004 L.OR R11,R4,R0# изпълнява се преди „L.JR“! Xilinx MicroBlaze GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global putvlq #//Регистри: value = R5, dest = R6, buffer = R7 19 putvlq: #putVLQ(unsigned value, unsigned char *dest) { 20 0000 7F00E5A4 ANDI R7,R5,0x7F # unsigned buffer = value & 0x7f; 21 0004 0700A564 L1: BSRLI R5,R5,7 # while ((value >>= 7) > 0) { 22 0008 180005BC BEQI R5,L2 23 000c 0804E764 BSLLI R7,R7,8 # buffer <<= 8; 24 0010 8000E7A0 ORI R7,R7,0x80 # buffer |= 0x80; 25 0014 7F0005A5 ANDI R8,R5,0x7F # buffer += value & 0x7f; 26 0018 0040E700 ADD R7,R7,R8 27 001c E8FF00B8 BRI L1 # } for ( ; ; ) { 28 0020 0000E6F8 L2: SWI R7,R6,0 # *dest++ = (unsigned char)buffer; 29 0024 0100C620 ADDI R6,R6,1 # 30 0028 800007A5 ANDI R8,R7,0x80 # if (buffer & 0x80) 31 002c 0C0008BC BEQI R8,L3 #__ 32 0030 0800E764 BSRLI R7,R7,8 # \ buffer >>= 8; 33 0034 ECFF00B8 BRI L2 # \___ else return dest; 34 0038 08000FB6 L3: RTSD R15,8 # } 35 003c 00006680 OR R3,R6,R0 #}//върни dest в R3; изпълнява се преди „RTSD“! HPPA GAS putvlq.s page 1 1 ;unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 ;{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 ; unsigned buffer = value & 0x7f; 4 ; while ((value >>= 7) > 0) { 5 ; buffer <<= 8; 6 ; buffer |= 0x80; 7 ; buffer += value & 0x7f; 8 ; } 9 ; for ( ; ; ) { 10 ; *dest++ = (unsigned char)buffer; 11 ; if (buffer & 0x80) 12 ; buffer >>= 8; 13 ; else 14 ; return dest; 15 ; } 16 ;} 17 .text 18 .global putvlq ;%R26 = value, %R25 = dest, %R24 = buffer 19 putvlq: ;putVLQ(unsigned value, unsigned char *dest) { 20 0000 D3581BF9 EXTRU %R26,31,7,%R24 ; unsigned buffer = value & 0x7f; 21 0004 D340AB1A L1: SHD,<> %R0,%R26,7,%R26 ; while ((value >>= 7) > 0) { 22 0008 E800001A B,N L2;анул.се при >0 23 000c D31808F8 SHD %R24,%R24,24,%R24; buffer <<= 8; 24 0010 D7021CFF DEPI 1,24,1,%R24 ; buffer |= 0x80; 25 0014 E81F1FD5 B L1 ;изп.се след DEP ____ buffer += value & 0x7f; } 26 0018 D71A0C19 DEP %R26,31,7,%R24 ;__/ for ( ; ; ) { 27 001c C718C010 L2: BB,>= %R24,24,L3 ;__ ____ *dest++ = (unsigned char)buffer; 28 0020 0F381222 STBS,MA %R24,1(%R25) ;__X____ if (buffer & 0x80) 29 0024 E81F1FE5 B L2 ;изп.се след SHD \ __ buffer >>= 8; 30 0028 D3000AF8 SHD %R0,%R24,8,%R24 ;____X__ else return dest; 31 002c 0819025C L3: COPY %R25,%R28 ; } 32 0030 E840C002 BV,N (%R2) ;} //Върни указателя към следващия байт в %R28 32 00000000 Renesas / SuperH SH GAS Little Endian putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global putvlq 21 putvlq: !//Рег.: value = R4, dest = R5, buffer = R0 22 0000 F9E1 MOV #-7,R1 ! >> 7 putVLQ(unsigned value, unsigned char *dest) 23 0002 7FE2 MOV #0x7F,R2! & 0x7F { 24 0004 4360 MOV R4,R0 ! unsigned buffer = value 25 0006 7FC9 AND #0x7F,R0 ! & 0x7f; 26 0008 1D44 L1: SHLD R1,R4 ! while ((value >>= 7) 27 000a 4824 TST R4,R4 ! > 0) 28 000c 0589 BT L2 ! { 29 000e 1840 SHLL8 R0 ! buffer <<= 8; 30 0010 80CB OR #0x80,R0 ! buffer |= 0x80; 31 0012 4363 MOV R4,R3 ! value 32 0014 2923 AND R2,R3 ! & 0x7f; 33 0016 3C30 ADD R3,R0 ! buffer += 34 0018 F68B BF L1 !T=0 ! } for ( ; ; ) { 35 001a 0025 L2: MOV.B R0,@R5 !Недокументираната MOV.B R0,@R5+ не се поддържа от QEMU 36 001c 0175 ADD #1,R5 !++ ! *dest++ = (unsigned char)buffer; 37 001e 80C8 TST #0x80,R0 ! if (buffer & 0x80) 38 0020 0189 BT L3 !__ 39 0022 1940 SHLR8 R0 ! \ buffer >>= 8; 40 0024 F98B BF L2 ! \ 41 0026 0B00 L3: RTS ! \__ else return 42 0028 5360 MOV R5,R0 !изп.се преди „RTS“! dest; } } GAS for CRIS putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global putvlq ;//Рег.: value = R10, dest = R11, buffer = R12 21 putvlq: ;putVLQ(unsigned value, unsigned char *dest) 22 0000 6AC6 MOVE.D $R10,$R12 ;{ 23 0002 2FCF7F00 0000 AND.D 0x7F,$R12 ; unsigned buffer = value & 0x7f; 24 0008 E7A3 L1: LSRQ 7,$R10 ; while ((value >>= 7) > 0) { 25 000a C0A2 CMPQ 0,$R10 26 000c 0E30 BEQ L2 27 000e B005 NOP 28 0010 C8C3 LSLQ 8,$R12 ; buffer <<= 8; 29 0012 4FCF8000 OR.B 0x80,$R12 ; buffer |= 0x80; 30 0016 F3E0 BA L1; изпълнява се след „OR“ 31 0018 4AC7 OR.B $R10,$R12 ; buffer += value & 0xFF; 32 001a CBCF L2: MOVE.B $R12,[$R11+] ;___ } for ( ; ; ) { 33 001c 87C3 BTSTQ 7,$R12 ; \___ *dest++ = (unsigned char)buffer; 34 001e 0860 BPL L3 ;__ if (buffer & 0x80) 35 0020 B005 NOP ; \ 36 0022 F9E0 BA L2; изпълнява се след „LSRQ“ 37 0024 E8C3 LSRQ 8,$R12 ; \ buffer >>= 8; 38 0026 F0B9 L3: RET ; \_ else return dest; 39 0028 6BA60000 MOVE.D $R11,$R10; изпълнява се преди „RET“ BFIN GAS putvlq.s page 1 1 #unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 2 #{ // (вж. Standard MIDI-File Format Spec. 1.1) 3 # unsigned buffer = value & 0x7f; 4 # while ((value >>= 7) > 0) { 5 # buffer <<= 8; 6 # buffer |= 0x80; 7 # buffer += value & 0x7f; 8 # } 9 # for ( ; ; ) { 10 # *dest++ = (unsigned char)buffer; 11 # if (buffer & 0x80) 12 # buffer >>= 8; 13 # else 14 # return dest; 15 # } 16 #} 17 18 .global _putvlq #// value = R0, dest = R1 -> P0, buffer = R1 19 _putvlq: #putVLQ(unsigned value, unsigned char *dest) 20 0000 0132 P0 = R1; #{ 21 0002 22E17F00 R2 = 0x7F; 22 0006 5054 R1 = R0 & R2; # unsigned buffer = value & 0x7f; 23 0008 384E L_1: R0 >>= 7; # while ((value >>= 7) > 0) { 24 000a 0003 CC = AZ; 25 000c 0618 IF CC JUMP L_2; 26 000e 414F R1 <<= 8; # buffer <<= 8; 27 0010 394A BITSET (R1, 7); # buffer |= 0x80; 28 0012 D054 R3 = R0 & R2; 29 0014 5950 R1 = R1 + R3; # buffer += value & 0x7f; 30 0016 F92F JUMP L_1; # } 31 0018 019A L_2: B [P0++] = R1; #___ for ( ; ; ) { 32 001a 3949 CC = BITTST (R1, 7); # \___ *dest++ = (unsigned char)buffer; 33 001c 0310 IF !CC JUMP L_3; #__ if (buffer & 0x80) 34 001e 414E R1 >>= 8; # \ buffer >>= 8; 35 0020 FC2F JUMP L_2; # \___ else return dest; 36 0022 4030 L_3: R0 = P0; # } 37 0024 10000000 RTS; #} //Върни указателя към следващия байт в R0 Hexagon GAS putvlq.s page 1 1 /* 2 unsigned char *putVLQ(unsigned value, unsigned char *dest) // запиши ВПД 3 { // (вж. Standard MIDI-File Format Spec. 1.1) 4 unsigned buffer = value & 0x7f; 5 while ((value >>= 7) > 0) { 6 buffer <<= 8; 7 buffer |= 0x80; 8 buffer += value & 0x7f; 9 } 10 for ( ; ; ) { 11 *dest++ = (unsigned char)buffer; 12 if (buffer & 0x80) 13 buffer >>= 8; 14 else 15 return dest; 16 } 17 } 18 */ 19 20 .global putvlq // Регистри: value = R0, dest = R1, buffer = R2 21 putvlq: //putVLQ(unsigned value, unsigned char *dest) { 22 0000 E2CF0076 R2 = AND(R0,#0x7F) // unsigned buffer = value & 0x7f; 23 0004 20C7008C L1: R0 = LSR(R0,#7) // while ((value >>= 7) > 0) { 24 0008 0AC08061 IF (R0==#0) JUMP:NT L2 25 000c 42C8028C R2 = ASL(R2,#8) // buffer <<= 8; 26 0010 02D08276 R2 = OR(R2,#0x80) // buffer |= 0x80; 27 { R2 = INSERT(R0,#7,#0)// buffer += value & 0x7f; 28 0014 0247008F F8FFFF59 JUMP L1 } // } for ( ; ; ) { 29 L2: { MEMB(R1++#1) = R2 // *dest++ = (unsigned char)buffer; 30 001c 00470285 08C201AB P0 = TSTBIT(R2,#7) } // if (buffer & 0x80) 31 { R2 = LSR(R2,#8) // buffer >>= 8; 32 0024 2248028C FCE0DF5C IF (P0) JUMP L2 } // else return dest; 33 { R0 = R1 // } 34 002c C03F1050 JUMPR LR } //} S/390 GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър 2 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 1744 L1: XR 4,4 # Нов текущ байт - започни натрупването от нулата 8 0002 1755 L2: XR 5,5 # Старшите байтове трябва да са 0 – IC не ги променя! 9 0004 43502000 IC 5,0(2) # Зареди поредния символ и засега приеми, че е цифра 10 0008 A72A0001 AHI 2,1 # Обнови адреса 11 000c A75AFFD0 AHI 5,-'0' # Преобразувай го от ASCII в двоичнодесетичен 12 0010 A7440007 JL L3 # Не е цифра? Излез от вътрешния цикъл 13 0014 A74C000A MHI 4,10 # Измести текущата стойност с 1 десетичен разред наляво 14 0018 1E45 ALR 4,5 # Добави цифрата към нея 15 001a A7F4FFF4 J L2 # Продължи със следващия символ от низа 16 001e 89300008 L3: SLL 3,8 # Направи място за още един байт 17 0022 1634 OR 3,4 # Запиши текущия байт най-отдясно 18 0024 A75EFFD0 CHI 5,-'0' # Нулев терминатор ли е бил този байт? 19 0028 A774FFEC JNE L1 # Не, значи е бил разделител ('.') 20 002c 1823 LR 2,3 # Да, върни IP-адреса в рег. 2 21 002e 07FE BR 14 ==> id32/getipstr.s <== 1 * Return in register 0 the IP-address (IPv4), obtained from the ASCIIZ string 2 * starting at 7(0) -> reg. 2. The string is in decimal format with a dot as a 3 * delimiter between the bytes (e.g. 192.92.129.2). 4 5 entry getipstr 00000000d 6 getipstr equ * 00000d 5827 0000 7 l 2,0(7) String buffer address 00004d 241A 8 lis 1,10 Multiplier 00006d 0744 9 L1 xr 4,4 New current byte - start accumulating from zero 00008d D332 0000 10 L2 lb 3,0(2) Load next character and assume it's a digit for now 0000Cd 2621 11 ais 2,1 Update the address 0000Ed CB30 0030 12 shi 3,c'0' Convert from ASCII to BCD 00012d 2184 0000001Ad 13 bls L3 Not a digit? Exit the inner loop 00014d 0C41 14 mhr 4,1 Shift the current byte left by 1 decimal place 00016d 0A43 15 ar 4,3 Add the new digit to it 00018d 2208 00000008d 16 bs L2 Continue with the next character of the string 0001Ad 1108 17 L3 slls 0,8 Make room for one more byte 0001Cd 0604 18 or 0,4 Write the current byte from the right 0001Ed C930 FFD0 19 chi 3,-c'0' Was this byte a zero terminator? 00022d 203E 00000006d 20 bnzs L1 No, then it was a delimiter ('.') 00024d 030F 21 br 15 Yes, return the IP-address in register 0 VAX GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в AP(4) -> R2. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global _getipstr 6 _getipstr: 7 0000 7C00 .word 0x7C # R2-R6: R2 = адрес на низа, R3 = байт, R5 = символ 8 0002 D0AC0452 MOVL 4(AP),R2 # Начален адрес на низа 9 0006 FD7C53 L1: CLRO R3 # Нов байт - започни натрупване от 0 (нулирай и R5) 10 0009 83308255 L2: SUBB3 $'0',(R2)+,R5#Приеми символа за цифра; преобразувай го от ASCII 11 000d 1F07 BLSSU L3 # Наистина ли е цифра? 12 000f 7A0A5355 53 EMUL $10,R3,R5,R3# Да – добави я към удесеторената текуща стойност 13 0014 11F3 BRB L2 # и продължи със следващия символ от низа 14 0016 7A8F0001 00005053 50 L3: EMUL $256,R0,R3,R0#Не – добави новия байт към натрупания IP-адрес 15 001f 9D8FD08F D255DFFF ACBB $-'0',$-'.',R5,L1# Ако символът е бил разделител, продължи; 16 0027 04 RET # в противен случай върни IP-адреса в R0 ==> we32k/getipstr.s <== # Return in the r0 register the IP-address (IPv4), obtained from the ASCIIZ # string starting at ap(0) -> r7. The string is in decimal format with a dot # as a delimiter between the bytes (e.g. 192.92.129.2). section .text .globl getipstr getipstr() getipstr: 0: 10 47 SAVE %r7 # "AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 47 MOVW 0(%ap),%r7# Programming Manual", pp. 6-13, 6-14 5: 70 NOP 6: 80 41 L1: CLRW %r1 # New current byte - start accumulating from zero 8: 87 57 42 L2: MOVB (%r7),%r2 # Load next character and assume it's a digit for now b: 70 NOP c: 90 47 INCW %r7 # Update the address e: ff 30 42 48 SUBB3 &0x30,%r2,%r8 # Convert from ASCII to BCD 12: 5b 0a BLUB L3 # Not a digit? Exit the inner loop 14: ab 0a 41 MULB2 &10,%r1 # Shift the current byte left by 1 decimal place 17: 9f 48 41 ADDB2 %r8,%r1 # Add the new digit to it 1a: 7b ee BRB L2 # Continue with the next character of the string 1c: d0 08 40 40 L3: LLSW3 &8,%r0,%r0# Make room for one more byte 20: 9c 41 40 ADDW2 %r1,%r0 # Write the current byte from the right 23: 2b 42 TSTB %r2 # Was this byte a zero terminator? 25: 77 e0 BNEB L1 # No, then it was a delimiter ('.') 27: 04 c9 f0 4c MOVAW -16(%fp),%sp RESTORE %r7 # Yes, restore the saved register 2b: 20 48 POPW %r8 2d: 20 47 POPW %r7 2f: 20 49 POPW %fp 31: 08 RET # and return the IP-address in r0 32: 70 NOP 33: 70 NOP 68K GAS getipstr.s page 1 1 | Да се напише подпрограма, която да връща в регистър D0 IP-адреса (IPv4), 2 | получен от низа тип ASCIIZ с начален адрес, подаден в SP(4) -> A0. Низът е 3 | в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 206F 0004 MOVEL 4(%SP),%A0 | Начален адрес на низа 8 0004 2F02 MOVEL %D2,-(%SP) | GCC изисква D2 да се съхранява 9 0006 4281 L1: CLRL %D1 | Нов текущ байт - започни натрупването от нулата 10 0008 1418 L2: MOVEB (%A0)+,%D2 | Зареди поредния символ и засега приеми, че е цифра 11 000a 0402 0030 SUBIB #'0',%D2 | Преобразувай от ASCII в двоичнодесетичен код 12 000e 6508 BLOB L3 | Не е цифра? Излез от вътрешния цикъл 13 0010 C2FC 000A MULUW #10,%D1 | Измести текущия байт с 1 десетичен разред наляво 14 0014 D202 ADDB %D2,%D1 | Добави новата цифра към него 15 0016 60F0 BRAB L2 | Продължи със следващия символ от низа 16 0018 E188 L3: LSLL #8,%D0 | Направи място за още един байт 17 001a 1001 MOVEB %D1,%D0 | Запиши текущия байт най-отдясно 18 001c 0C02 FFD0 CMPIB #-'0',%D2 | Нулев терминатор ли е бил този байт? 19 0020 66E4 BNEB L1 | Не, значи е бил разделител ('.') 20 0022 241F MOVEL (%SP)+,%D2 | Да, въстанови съхранения регистър 21 0024 4E75 RTS | и върни IP-адреса в D0 x86 NASM getipstr.s 1 ; Да се напише подпрограма, която да връща в регистър EAX IP-адреса (IPv4), 2 ; получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът е 3 ; в десетичен формат с разделител между байтовете точка (пример: 192.92.129.2). 4 5 section .text 6 global getipstr,_getipstr; в GCC декларирай с __attribute__((regparm(3))) 7 getipstr: 8 _getipstr: 9 00000000 56 PUSH ESI ; GCC изисква ESI да се запази 10 00000001 96 XCHG EAX,ESI ; Началният адрес е удобно да бъде в ESI заради LODSB 11 00000002 31C0 L1: XOR EAX,EAX ; Нов текущ байт - започни натрупването от нулата 12 00000004 D50A L2: AAD ; Добави цифрата към удесеторената текуща ст. на байта 13 00000006 88C4 MOV AH,AL ; Запази текущата стойност на байта 14 00000008 AC LODSB ; Зареди поредния символ и засега приеми, че е цифра 15 00000009 2C30 SUB AL,'0' ; Преобразувай го от ASCII в двоичнодесетичен 16 0000000B 73F7 JAE L2 ; Цифра? Продължи със следващия символ от низа 17 0000000D C1E108 SHL ECX,8 ; Направи място за текущия байт 18 00000010 88E1 MOV CL,AH ; и го запиши най-отдясно в IP-адреса 19 00000012 3CD0 CMP AL,-'0' ; Нулев терминатор ли е бил този байт? 20 00000014 75EC JNE L1 ; Не, значи е бил разделител ('.') 21 00000016 91 XCHG EAX,ECX ; Върни IP-адреса в EAX 22 00000017 5E POP ESI ; Възстанови ESI и върни управлението 23 00000018 C3 RET ARM GAS getipstr.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 IP-адреса (IPv4), 2 // получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 // е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 0AC0A0E3 MOV R12,#10 // Основа на бройната система на низа 8 0004 0020A0E3 L1: MOV R2,#0 // Нов текущ байт - започни натрупването от нулата 9 0008 0130D0E4 L2: LDRB R3,[R0],#1// Зареди поредния символ и засега приеми, че е цифра 10 000c 303053E2 SUBS R3,R3,#'0'// Преобразувай го от ASCII в двоичнодесетичен 11 0010 9C322220 MLAHS R2,R12,R2,R3//Цифра? Добави я към удесеторената текуща стойност 12 0014 FBFFFF2A BHS L2 // и продължи със следващия символ от низа 13 0018 011482E0 ADD R1,R2,R1,LSL #8// Добави новия байт към натрупания IP-адрес 14 001c 300073E3 CMP R3,#-'0' // Нулев терминатор ли е бил този байт? 15 0020 F7FFFF1A BNE L1 // Не, значи е бил разделител ('.') 16 0024 0100A0E1 MOV R0,R1 // Да, върни IP-адреса в R0 17 0028 1EFF2FE1 BX LR ARC GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър r0 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 4C70 L1: MOV_S r2,0 # Нов текущ байт - започни натрупването от нулата 8 0002 0110 8304 L2: LDB.AB r3,[r0,1] # Зареди поредния символ и засега приеми, че е цифра 9 0006 4223 038C SUB.F r3,r3,'0' # Преобразувай го от ASCII в двоичнодесетичен 10 000a DA22 A602 MPY.HS r2,r2,10 # Ако символът е бил цифра, измести текущия байт с 1 11 000e C022 C600 ADD.HS r2,r2,r3 # десетичен разред наляво, добави към него тая цифра 12 0012 79F7 BHS_S L2 # и продължи със следващия символ от низа 13 0014 08B9 ASL_S r1,r1,8 # Иначе направи място за новия байт 14 0016 5961 ADD_S r1,r1,r2 # и го добави към натрупания IP-адрес 15 0018 E90B 818F FFFF D0FF BRNE r3,-'0',L1 # Ако силволът не е бил терминатор (0), а разделител 16 0020 2040 MOV_S r0,r1 # ('.'), продължи цикъла, иначе върни IP-адреса в r0 17 0022 E07E J_S [blink] PPC GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър r3 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 3883FFFF addi r4,r3,-1# Компенсирай преинкрементната адресация 8 0004 38A00000 L1: li r5,0 # Нов текущ байт - започни натрупването от нулата 9 0008 8CC40001 L2: lbzu r6,1(r4)# Зареди поредния символ и засега приеми, че е цифра 10 000c 34C6FFD0 addic. r6,r6,-'0#Преобразувай го от ASCII в двоичнодесетичен 11 0010 41800010 blt L3 # Не е цифра? Излез от вътрешния цикъл 12 0014 1CA5000A mulli r5,r5,10# Измести текущата стойност с 1 десетичен разред наляво 13 0018 7CA53214 add r5,r5,r6# Добави цифрата към нея 14 001c 4BFFFFEC b L2 # Продължи със следващия символ от низа 15 0020 5463402E L3: slwi r3,r3,8 # Направи място за още един байт 16 0024 7C632B78 or r3,r3,r5# Запиши текущия байт най-отдясно 17 0028 2C06FFD0 cmpwi r6,-'0 # Нулев терминатор ли е бил този байт? 18 002c 4082FFD8 bne L1 # Не, значи е бил разделител ('.') 19 0030 4E800020 blr # Да, върни управлението SPARC GAS getipstr.s page 1 1 ! Да се напише подпрограма, която да връща в регистър %o0 IP-адреса (IPv4), 2 ! получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 ! е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 94100000 L1: clr %o2 ! Нов текущ байт - започни натрупването от нулата 8 0004 D60A0000 L2: ldub [%o0],%o3 ! Зареди поредния символ и засега приеми, че е цифра 9 0008 96A2E030 subcc %o3,'0',%o3! Преобразувай символа от ASCII в двоичнодесетичен 10 000c 0A800005 bcs L3 ! Не е цифра? Излез от вътрешния цикъл 11 0010 90022001 inc %o0 ! Обнови адреса (изпълнява се преди „bcs“!) 12 0014 9452A00A umul %o2,10,%o2!Измести текущата стойност вляво с 1 десетичен разред 13 0018 10BFFFFB ba L2 ! Зареди следващия символ (изпълнява се след „add“!) 14 001c 9402800B add %o2,%o3,%o2! Добави цифрата към нея 15 0020 932A6008 L3: sll %o1,8,%o1 ! Направи място за още един байт 16 0024 80A2FFD0 cmp %o3,-'0' ! Нулев терминатор ли е бил този байт? 17 0028 12BFFFF6 bne L1 ! Не, значи е бил разделител ('.') 18 002c 9212400A or %o1,%o2,%o1!Да, запиши байта вдясно (изпълнява се преди „bne“!) 19 0030 81C3E008 retl 20 0034 90100009 mov %o1,%o0 ! Върни адреса в %o0 (изпълнява се преди „retl“!) MIPS GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър $2 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в регистър $4. Низът е 3 # в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .ent getipstr 6 .global getipstr 7 getipstr: 8 0000 2408000A LI $8,10 # Основа на бройната система 9 0004 2407FFD0 LI $7,-'0' # Подготви преобразуването от ASCII 10 0008 24060000 L1: LI $6,0 # Нов текущ байт - започни натрупването от нулата 11 000c 90850000 L2: LBU $5,0($4)# Зареди поредния символ и засега приеми, че е цифра 12 0010 24840001 ADDIU $4,$4,1 # Обнови адреса 13 0014 00A72821 ADDU $5,$5,$7# Преобразувай символа от ASCII в двоичнодесетичен 14 0018 04A00004 00000000 BLTZ $5,L3 # Не е цифра? Излез от вътрешния цикъл 15 0020 70C83002 MUL $6,$6,$8# Измести текущата стойност вляво с 1 десетичен разред 16 ADDU $6,$6,$5# Добави цифрата към нея 17 0024 1000FFF9 00C53021 B L2 # Продължи със следващия символ от низа 18 002c 00021200 L3: SLL $2,$2,8 # Направи място за още един байт 19 OR $2,$2,$6# Запиши текущия байт най-отдясно 20 0030 14A7FFF5 00461025 BNE $5,$7,L1# Байтът не е бил нулев терминатор, а разделител ('.') 21 0038 03E00008 00000000 JR $31 # Върни управлението 22 .end getipstr RISC-V GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър a0 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 2947 LI a4,10 # Основа на бройната система 8 0002 930600FD LI a3,-'0' # Подготви преобразуването от ASCII 9 0006 0146 L1: LI a2,0 # Нов текущ байт - започни натрупването от нулата 10 0008 83450500 L2: LBU a1,0(a0)# Зареди поредния символ и засега приеми, че е цифра 11 000c 0505 ADDI a0,a0,1 # Обнови адреса 12 000e B695 ADD a1,a1,a3# Преобразувай символа от ASCII в двоичнодесетичен 13 0010 63C60500 BLTZ a1,L3 # Не е цифра? Излез от вътрешния цикъл 14 0014 3306E602 MUL a2,a2,a4# Измести текущата стойност вляво с 1 десетичен разред 15 0018 2E96 ADD a2,a2,a1# Добави цифрата към нея 16 001a FDB7 J L2 # Продължи със следващия символ от низа 17 001c A207 L3: SLLI a5,a5,8 # Направи място за още един байт 18 001e D18F OR a5,a5,a2# Запиши текущия байт най-отдясно 19 0020 E393D5FE BNE a1,a3,L1# Байтът не е бил нулев терминатор, а разделител ('.') 20 0024 3E85 MV a0,a5 # Върни IP-адреса в a0 21 0026 8280 RET # Върни управлението Nios II GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в регистър r4. Низът е 3 # в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 94020002 MOVUI r8,10 # Основа на бройната система 8 0004 04F4FF01 MOVI r7,-'0' # Подготви преобразуването от ASCII 9 0008 14008001 L1: MOVUI r6,0 # Нов текущ байт - започни натрупването от нулата 10 000c 03004021 L2: LDBU r5,(r4) # Зареди поредния символ и засега приеми, че е цифра 11 0010 44000021 ADDI r4,r4,1 # Обнови адреса 12 0014 3A88CB29 ADD r5,r5,r7# Преобразувай символа от ASCII в двоичнодесетичен 13 0018 16030028 BLT r5,r0,L3# Не е цифра? Излез от вътрешния цикъл 14 001c 3A380D32 MUL r6,r6,r8# Измести текущата стойност вляво с 1 десетичен разред 15 0020 3A884D31 ADD r6,r6,r5# Добави цифрата към нея 16 0024 06F93F00 BR L2 # Продължи със следващия символ от низа 17 0028 3A920410 L3: SLLI r2,r2,8 # Направи място за още един байт 18 002c 3AB08411 OR r2,r2,r6# Запиши текущия байт най-отдясно 19 0030 1EF5FF29 BNE r5,r7,L1# Байтът не е бил нулев терминатор, а разделител ('.') 20 0034 3A2800F8 RET # Върни управлението Xtensa GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър a2 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 0CA6 MOVI a6,10 # Основа на бройната система 8 0002 52AFD0 MOVI a5,-'0' # Подготви преобразуването от ASCII 9 0005 0C04 L1: MOVI a4,0 # Нов текущ байт - започни натрупването от нулата 10 0007 320200 L2: L8UI a3,a2,0 # Зареди поредния символ и засега приеми, че е цифра 11 000a 1B22 ADDI a2,a2,1 # Обнови адреса 12 000c 5A33 ADD a3,a3,a5# Преобразувай символа от ASCII в двоичнодесетичен 13 000e 967300 BLTZ a3,L3 # Не е цифра? Излез от вътрешния цикъл 14 0011 604482 MULL a4,a4,a6# Измести текущата стойност вляво с 1 десетичен разред 15 0014 3A44 ADD a4,a4,a3# Добави цифрата към нея 16 0016 46FBFF J L2 # Продължи със следващия символ от низа 17 0019 807711 L3: SLLI a7,a7,8 # Направи място за още един байт 18 001c 407720 OR a7,a7,a4# Запиши текущия байт най-отдясно 19 001f 5793E2 BNE a3,a5,L1# Байтът не е бил нулев терминатор, а разделител ('.') 20 0022 2D07 MOV a2,a7 # Върни IP-адреса в a2 21 0024 0DF0 RET # Върни управлението 88K GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global _getipstr 6 0000 F4625800 _getipstr: 7 0004 F4805800 or r3,r2,r0 # Начален адрес на низа (освободи r2 за IP-адреса) 8 0008 F4A30C00 L1: or r4,r0,r0 # Нов текущ байт - започни натрупването от нулата 9 000c 60630001 L2: ld.bu r5,r3,r0 # Зареди поредния символ и засега приеми, че е цифра 10 0010 64A50030 addu r3,r3,1 # Обнови адреса 11 0014 E9850004 subu r5,r5,'0'# Преобразувай го от ASCII в двоичнодесетичен 12 0018 6C84000A bcnd lt0,r5,L3# Не е цифра? Излез от вътрешния цикъл 13 001c F4846005 mul r4,r4,10 #Измести текущата стойност с 1 десетичен разред наляво 14 0020 C3FFFFFA addu r4,r4,r5 # Добави цифрата към нея 15 0024 F042A008 br L2 # Продължи със следващия символ от низа 16 0028 F4425804 L3: mak r2,r2,0<8>#Направи място за още един байт 17 002c 60A50030 or r2,r2,r4 # Запиши текущия байт най-отдясно 18 0030 E9A5FFF5 addu r5,r5,'0'# Нулев терминатор ли е бил този байт? 19 0034 F400C001 bcnd ne0,r5,L1# Не, значи е бил разделител ('.') jmp r1 # Да, върни управлението Or1k GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър R11 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в регистър R3. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 E0A00004 L1: L.OR R5,R0,R0 # Нов текущ байт - започни натрупването от нулата 8 0004 8C830000 L2: L.LBZ R4,0(R3) # Зареди поредния символ и засега приеми, че е цифра 9 0008 9C84FFD0 L.ADDI R4,R4,-'0'# Преобразувай символа от ASCII в двоичнодесетичен 10 000c E5640000 L.SFGES R4,R0 # Цифра? 11 0010 0C000005 L.BNF L3 # Не, излез от вътрешния цикъл 12 0014 9C630001 L.ADDI R3,R3,1 # Обнови адреса (изпълнява се преди „L.BNF“!) 13 0018 B0A5000A L.MULI R5,R5,10 #Измести текущата стойност вляво с 1 десетичен разред 14 001c 03FFFFFA L.J L2 # Зареди следващия символ (изпълн. се след „L.ADD“!) 15 0020 E0A52000 L.ADD R5,R5,R4 # Добави цифрата към текущата стойност 16 0024 B96B0008 L3: L.SLLI R11,R11,8 # Направи място за още един байт 17 0028 BC24FFD0 L.SFNEI R4,-'0' # Нулев терминатор ли е бил този байт? 18 002c 13FFFFF5 L.BF L1 # Не, значи е бил разделител ('.') 19 0030 E1655804 L.OR R11,R5,R11# Да, запиши байта вдясно (изпълн. се преди „L.BF“!) 20 0034 44004800 L.JR LR # Върни адреса в R11 21 0038 15000000 L.NOP 0 Xilinx MicroBlaze GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър R5 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в регистър R5. Низът е 3 # в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 0000E080 L1: OR R7,R0,R0# Нов текущ байт - започни натрупването от нулата 8 0004 000005E1 L2: LBUI R8,R5,0 # Зареди поредния символ и засега приеми, че е цифра 9 0008 0100A520 ADDI R5,R5,1 # Обнови адреса 10 000c D0FF0821 ADDI R8,R8,-'0'#Преобразувай символа от ASCII в двоичнодесетичен 11 0010 100048BC BLTI R8,L3 # Не е цифра? Излез от вътрешния цикъл 12 0014 0A00E760 MULI R7,R7,10# Измести текущата стойност с 1 десетичен разред наляво 13 0018 0040E700 ADD R7,R7,R8# Добави цифрата към нея 14 001c E8FF00B8 BRI L2 # Продължи със следващия символ от низа 15 0020 08046364 L3: BSLLI R3,R3,8 # Направи място за още един байт 16 0024 00386380 OR R3,R3,R7# Запиши текущия байт най-отдясно 17 0028 30000821 ADDI R8,R8,'0'#Нулев терминатор ли е бил този байт? 18 002c D4FF28BC BNEI R8,L1 # Не, значи е бил разделител ('.') 19 0030 08000FB6 RTSD R15,8 # Да, върни управлението 20 0034 00000080 NOP HPPA GAS getipstr.s page 1 1 ; Да се напише подпрограма, която да връща в регистър %R28 IP-адреса (IPv4), 2 ; получен от низа тип ASCIIZ с начален адрес, подаден в регистър %R26. Низът 3 ; е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .text 6 .global getipstr 7 getipstr: ; %R26 = адрес на низа, %R25 = байт, %R24 = символ 8 0000 34190000 L1: LDI 0,%R25 ; Нов байт - започни натрупването от нулата 9 0004 0F421038 L2: LDBS,MA 1(%R26),%R24; Зареди поредния символ. Засега приеми, че е цифра 10 0008 C778C018 BB,>= %R24,27,L3 ; '.' (2E) или 0? Байтът готов (пров.се преди DEPI) 11 000c D7001C9E DEPI 0,27,2,%R24 ; Преобразувай от ASCII (изпълнява се преди „BB“!) 12 0010 0B390A99 SH2ADDL %R25,%R25,%R25; Умножи текущата стойност на байта по 5, ... 13 0014 E81F1FD5 B L2 ; (продължи със следващия символ от низа) 14 0018 0B190A59 SH1ADDL %R25,%R24,%R25; удвои я и добави цифрата (изпълн.се преди „B“!) 15 001c D79C0908 L3: ZDEP %R28,23,24,%R28; Измести натрупания IP-адрес с 8 бита наляво... 16 0020 8F003FB5 COMIBF,= 0,%R24,L1 ; (ако символът е бил '.', а не 0, продължи) 17 0024 0B3C061C ADD %R28,%R25,%R28; и добави новия байт (изпълн.се преди „COMIBF“!) 18 0028 E840C002 BV,N (%R2) ; Върни IP-адреса в %R28 18 00000000 Renesas / SuperH SH GAS Little Endian getipstr.s page 1 1 ! Да се напише подпрограма, която да връща в регистър R0 IP-адреса (IPv4), 2 ! получен от низа тип ASCIIZ с начален адрес, подаден в регистър R4. Низът е 3 ! в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 0AE1 MOV #10,R1 ! Подготви множителя за „MUL.L“ 8 0002 D0E5 MOV #-'0',R5! и събираемото за „ADD“ (то ще е и умалител за „CMP“) 9 0004 00E2 L1: MOV #0,R2 ! Нов текущ байт - започни натрупването от нулата 10 0006 4463 L2: MOV.B @R4+,R3 ! Зареди поредния символ и засега приеми, че е цифра 11 0008 D073 ADD #-'0',R3! Преобразувай символа от ASCII в двоичнодесетичен 12 000a 1143 CMP/PZ R3 ! Цифра ли е все пак? 13 000c 038B BF L3 ! Не, излез от вътрешния цикъл 14 000e 1702 MUL.L R1,R2 ! Измести текущата стойност вляво с 1 десетичен разред 15 0010 1A02 STS MACL,R2 16 0012 3C32 ADD R3,R2 ! Добави цифрата към нея 17 0014 F789 BT L2 ! Зареди следващия символ 18 0016 1840 L3: SHLL8 R0 ! Направи място за още един байт 19 0018 5033 CMP/EQ R5,R3 ! Нулев терминатор ли е бил този байт? 20 001a 2B20 OR R2,R0 ! (Запиши преобразувания байт вдясно) 21 001c F28B BF L1 ! Не, значи е бил разделител ('.') 22 001e 0B00 RTS ! Да, върни IP-адреса в R0 23 0020 0900 NOP GAS for CRIS getipstr.s page 1 1 ; Да се напише подпрограма, която да връща в регистър R10 IP-адреса (IPv4), 2 ; получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 ; е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 7C86 L1: CLEAR.D $R12 ; Нов текущ байт - започни натрупването от нулата 8 0002 4ADC L2: MOVU.B [$R10+],$R13;Зареди поредния символ и засега приеми, че е цифра 9 0004 B0D2 SUBQ '0',$R13 ; Преобразувай символа от ASCII в двоичнодесетичен 10 0006 0A10 BLO L3 ; Не е цифра? Излез от вътрешния цикъл 11 0008 4A92 MOVEQ 10,$R9 ; Подготви множителя (изпълнява се след „BLO“!) 12 000a 29C9 MULU.D $R9,$R12 ; Измести текущата стойн. вляво с 1 десетичен разред 13 000c F7E0 BA L2 ; Зареди следващия символ (изпълнява се след „ADD“!) 14 000e 2DC6 ADD.D $R13,$R12 ; Добави цифрата към нея 15 0010 C8B3 L3: LSLQ 8,$R11 ; Направи място за още един байт 16 0012 EFDCD0FF CMPS.B -'0',$R13 ; Нулев терминатор ли е бил този байт? 17 0016 EB20 BNE L1 ; Не, значи е бил разделител ('.') 18 0018 6CB7 OR.D $R12,$R11 ; Да, запиши байта вдясно (изпълн. се преди „BNE“!) 19 001a F0B9 RET 20 001c 6BA60000 MOVE.D $R11,$R10 ; Върни адреса в $R10 (изпълнява се преди „RET“!) BFIN GAS getipstr.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 IP-адреса (IPv4), 2 # получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 # е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global _getipstr 6 _getipstr: 7 0000 0032 P0 = R0; # Адресът трябва да е в адресен регистър 8 0002 5360 R3 = 10 (X); # Основа на бройната система 9 0004 9258 L_1: R2 = R2 ^ R2; # Нов текущ байт - започни натрупването от нулата 10 0006 0198 L_2: R1 = B [P0++] (Z);# Зареди поредния символ и засега приеми, че е цифра 11 0008 8166 R1 += -'0'; # Преобразувай символа от ASCII в двоичнодесетичен 12 000a 0C03 CC = AC0; # AC0 след изваждане е обратен: 82-000556-01, стр. 11-3 13 000c 0410 IF !CC JUMP L_3;# Не е цифра? Излез от вътрешния цикъл 14 000e DA40 R2 *= R3; # Измести текущата стойност вляво с 1 десетичен разред 15 0010 8A50 R2 = R2 + R1; # Добави цифрата към нея 16 0012 FA2F JUMP L_2; # Продължи със следващия символ от низа 17 0014 404F L_3: R0 <<= 8; # Направи място за още един байт 18 0016 1056 R0 = R0 | R2; # Запиши текущия байт най-отдясно 19 0018 310C CC = R1 == '.' - '0';# Разделител ('.') ли е бил ASCII-кодът? 20 001a F51B IF CC JUMP L_1; # Да, продължи със следващия байт 21 001c 10000000 RTS; # Не, бил е терминатор ('\0') – върни IP-адреса в R0 Hexagon GAS getipstr.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 IP-адреса (IPv4), 2 // получен от низа тип ASCIIZ с начален адрес, подаден в същия регистър. Низът 3 // е в десетичен формат с разделител между байтовете точка (напр. 192.92.129.2) 4 5 .global getipstr 6 getipstr: 7 0000 02C00078 L1: R2 = #0 // Нов текущ байт - започни натрупването от нулата 8 0004 23C0209B L2: R3 = MEMUB(R0++#1)// Зареди нов символ и засега приеми, че е цифра 9 { P0 = CMP.EQ(R3,#0) // Ако е нулев терминатор, P0 = 0xFF, иначе 0 10 P1 = CMP.GEU(R3,#'0')// Ако е ASCII-код на цифра, P1 = 0xFF, иначе 0 11 R3 = ADD(R3,#-'0') // Преобразувай го от ASCII в двоичнодесетичен 12 0008 444102E0 E1458375 30390325 R4 = MPYI(R2,#10) } // Цифра? Измести текущата стойност с 1 десети- 13 { IF (P1) R2 = ADD(R4,R3)// чен разред наляво, добави цифрата към нея 14 0014 224304FB 00C1005C IF (P1) JUMP L2 } // и продължи със следващия символ от низа 15 001C 41C8018C R1 = ASL(R1,#8) // Направи място за новия байт 16 { R1 = ADD(R1,R2) // и го добави към натрупания IP-адрес 17 0020 01C201F3 F070FF5C IF (!P0) JUMP:T L1 } // Байтът е бил разделител ('.') – продължи 18 { R0 = R1 // Да, върни IP-адреса в R0 19 0028 C03F1050 JUMPR LR } S/390 GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър 3, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър 2. 4 5 .global putipstr 6 putipstr: 7 0000 5060F008 ST 6,8(15) # Съхрани използвания регистър (LNUX-1007-02) 8 0004 C0600000 0036 LARL 6,ZDELIM # Подготви 3 разделителя и 1 терминатор (0) 9 000a 58006000 L 0,0(6) 10 000e 1852 L1: LR 5,2 11 0010 88500018 SRL 5,24 # Зареди следващ байт (от старши към младши) 12 0014 89200008 SLL 2,8 # Измести IP-адреса с 1 байт наляво 13 0018 A75E0009 CHI 5,9 # Само единици ли имаме? 14 001c A7D4000E JNH L3 # Да, запиши ги направо, без нули пред тях 15 0020 A75E0063 CHI 5,99 # Има ли стотици? 16 0024 A7180064 LHI 1,100 # (подготви делителя) 17 0028 A7D40004 JNH L2 # Не, прескочи стотиците 18 002c A7650016 BRAS 6,Digit # Да, запиши първо тях 19 0030 A718000A L2: LHI 1,10 20 0034 A7650012 BRAS 6,Digit # Направи същото и с десетиците, 21 0038 A7180001 L3: LHI 1,1 # и с единиците 22 003c A765000E BRAS 6,Digit 23 0040 88000008 SRL 0,8 # Подготви следващия разделител или терминатор 24 0044 42003000 STC 0,0(3) # и го запиши в низа 25 0048 A73A0001 AHI 3,1 # Обнови указателя 26 004c 1200 LTR 0,0 # Последен байт? 27 004e A774FFE0 JNE L1 # Не, премини към обработка на следващия байт 28 0052 5860F008 L 6,8(15) # Да, възстанови съхранения регистър 29 0056 07FE BR 14 # и се върни в извикващата програма 30 31 0058 1744 Digit: XR 4,4 # Старшата дума на делимото трябва да е 0! 32 005a B9970041 DLR 4,1 # Рег. 5 = поредната цифра, рег. 4 = следващите 33 005e A75A0030 AHI 5,'0' # Преобразувай цифрата в ASCII-код 34 0062 42503000 STC 5,0(3) # и я запиши в низа 35 0066 A73A0001 AHI 3,1 # Обнови указателя 36 006a 1854 LR 5,4 # Остатъкът ще бъде следващото делимо 37 006c 07F6 BR 6 38 006e 0707 .align 4 39 0070 2E2E2E00 ZDELIM: .long '.' << 24 |'.' << 16 | '.' << 8 ==> id32/putipstr.s <== 1 * Write at an address passed in 7(4) -> reg. 3 an ASCIIZ string in decimal 2 * format without leading zeros and with a dot as a byte delimiter, obtained 3 * from an IP-address (IPv4) passed in 7(0) -> reg. 2. 4 5 entry putipstr 00000000d 6 putipstr equ * 00000d 5827 0000 7 l 2,0(7) IP-address 00004d 5837 0004 8 l 3,4(7) String buffer address 00008d F800 2E2E 2E00 9 li 0,x'2e2e2e00'(0) '.' << 24 |'.' << 16 | '.' << 8 (3 delimiters) 0000Ed 0842 10 L1 lr 4,2 00010d EC40 0018 11 srl 4,24(0) Load next byte (from high to low) 00014d 1128 12 slls 2,8 Shift the IP-address left by 1 byte 00016d C540 000A 13 clhi 4,10(0) Only ones? 0001Ad 218B 00000030d 14 bls L3 Yes, write them stright, without leading zeros 0001Cd C810 0064 15 lhi 1,100(0) No, prepare the divisor for eventual hundreds 00020d C540 0064 16 clhi 4,100(0) Any hundreds? 00024d 2183 0000002Ad 17 bls L2 No, skip them 00026d 4160 801C 00000046d 18 bal 6,Digit Yes, write them first 0002Ad 241A 19 L2 lis 1,10 0002Cd 4160 8016 00000046d 20 bal 6,Digit Do the same also with the tens 00030d 2411 21 L3 lis 1,1 and the ones 00032d 4160 8010 00000046d 22 bal 6,Digit 00036d 1008 23 srls 0,8 Prepare the next delimiter or terminator 00038d D203 0000 24 stb 0,0(3) and write it to the string 0003Cd 2631 25 ais 3,1 Update the address 0003Ed 0600 26 or 0,0 Was this the last byte? 00040d 4230 FFCA 0000000Ed 27 bnz L1(0) No, go process the next one 00044d 030F 28 br 15 Yes, return to the caller 29 00046d 0D41 30 Digit dhr 4,1 Reg. 5 = current digit (reg. 4 = the next ones) 00048d CA50 0030 31 ahi 5,c'0'(0) Convert the current digit to ASCII 0004Cd D253 0000 32 stb 5,0(3) Write it to the string 00050d 2631 33 ais 3,1 Update the address 00052d 0306 34 br 6 The remainder in reg.4 contains the next digits VAX GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в AP(8) -> R1, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в AP(4) -> R0. 4 5 .global _putipstr 6 _putipstr: 7 0000 3C00 .word 0x3C # R2-5; R0: IP-адр., R1: адр. на низа, R3: байт 8 0002 7DAC0450 MOVQ 4(AP),R0 9 0006 FD7D8F00 2E2E2E00 00000000 MOVO $'.' << 24 |'.' << 16 | '.' << 8,R2 # 3 разделителя; нулирай R4 9 00000000 00000052 10 001a EF180850 53 L1: EXTZV $24,$8,R0,R3 # Зареди следващ байт (от старши към младши) 11 001f 78085050 ASHL $8,R0,R0 # Измести IP-адреса с 1 байт наляво 12 0023 3D090053 1E00 ACBW $9,$0,R3,L3 # Само единици? Запиши ги направо, без водещи 0 13 0029 3D8F6300 00530D00 ACBW $99,$0,R3,L2 # Само десетици и единици? Прескочи стотиците 14 0031 7B8F6400 00005355 53 EDIV $100,R3,R5,R3 # Получи цифрата на стотиците, 15 003a 81305581 ADDB3 $'0',R5,(R1)+ # преобразувай я в ASCII-код и я запиши в низа 16 003e 7B0A5355 53 L2: EDIV $10,R3,R5,R3 # Направи същото и 17 0043 81305581 ADDB3 $'0',R5,(R1)+ # с десетиците 18 0047 81305381 L3: ADDB3 $'0',R3,(R1)+ # и единиците 19 004b EF081852 52 EXTZV $8,$24,R2,R2 # Подготви поредния разделител или терминатор 20 0050 905281 MOVB R2,(R1)+ # Запиши го в низа; последен ли е този байт? 21 0053 12C5 BNEQ L1 # Не: премини към обработка на следващия 22 0055 040101 RET # Да: възстанови регистрите, върни управлението ==> we32k/putipstr.s <== # Write at an address passed in ap(4) -> r1 an ASCIIZ string in decimal format # without leading zeros and with a dot as a byte delimiter, obtained from an # IP-address (IPv4) passed in ap(0) -> r0. section .text .globl putipstr putipstr() putipstr: 0: 10 47 SAVE %r7 #"AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 40 MOVW 0(%ap),%r0 # Programming Manual", pp. 6-13, 6-14 5: 84 74 41 MOVW 4(%ap),%r1 # r0 = string buffer address, r1 = IP-address 8: 84 4f 00 2e 2e 2e 42 MOVW &0x2E2E2E00,%r2 # '.' << 24 |'.' << 16 | '.' << 8, 3 delimiters f: cc 07 18 40 47 L1: EXTFW &7,&24,%r0,%r7 # Load next byte (from high to low) 14: d0 08 40 40 LLSW3 &8,%r0,%r0 # Shift the IP-address left by 1 byte 18: 3f 09 47 CMPB &9,%r7 # Only ones? 1b: 5b 2a BLUB L3 # Write them stright, without leading zeros 1d: 3f 6f 63 47 CMPB &99,%r7 # Only tens and ones? 21: 5b 14 BLUB L2 # Skip the hundreds 23: 87 47 48 MOVB %r7,%r8 DIVB3 &100,%r7,%r8 # Get the digit of the hundreds, 26: af 6f 64 48 DIVB2 &100,%r8 2a: df 30 48 51 ADDB3 &0x30,%r8,(%r1) # convert it to ASCII & write it to the string 2e: 70 NOP 2f: 90 41 INCW %r1 # Update the address 31: a7 6f 64 47 MODB2 &100,%r7 # The remainder contains the next digits 35: 87 47 48 MOVB %r7,%r8 L2: DIVB3 &10,%r7,%r8 # Do the same also with the tens 38: af 0a 48 DIVB2 &10,%r8 3b: df 30 48 51 ADDB3 &0x30,%r8,(%r1) 3f: 70 NOP 40: 90 41 INCW %r1 42: a7 0a 47 MODB2 &10,%r7 45: df 30 47 51 L3: ADDB3 &0x30,%r7,(%r1) # Finally, write the ones 49: 70 NOP 4a: 9c 02 41 ADDW2 &2,%r1 # Update the address, also for the next write 4d: d4 08 42 42 LRSW3 &8,%r2,%r2 # Prepare the next delimiter or terminator 51: 87 42 c1 ff MOVB %r2,-1(%r1) # Write it to the string. Was it the last byte? 55: 70 NOP 56: 77 b9 BNEB L1 # No - go process the next one 58: 04 c9 f0 4c MOVAW -16(%fp),%sp RESTORE %r7 # Yes - restore r7 and r8, return to the caller 5c: 20 48 POPW %r8 5e: 20 47 POPW %r7 60: 20 49 POPW %fp 62: 08 RET 63: 70 NOP 68K GAS putipstr.s page 1 1 | Да се напише подпрограма, която да записва от адрес, подаден в SP(8) -> A0, 2 | низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 | байтовете точка, получен от IP-адрес (IPv4), подаден в SP(4) -> D0. 4 5 .global putipstr 6 putipstr: 7 0000 4CEF 0101 0004 MOVEML 4(%SP),%D0/%A0 | D0: IP-адрес, A0: адрес на низа, D1: байт 8 0006 2F02 MOVEL %D2,-(%SP) | GCC изисква D2 да се съхранява 9 0008 243C 2E2E 2E00 MOVEL #('.' << 24) + ('.' << 16) + ('.' << 8),%D2 | 3 разделителя 10 000e E9C0 1008 L1: BFEXTU %D0{0:8},%D1 | Зареди следващ байт (от старши към младши) 11 0012 E188 LSLL #8,%D0 | Измести IP-адреса с 1 байт наляво 12 0014 0C01 0009 CMPIB #9,%D1 | Само единици? 13 0018 6322 BLSB L3 | Да, запиши ги направо, без водещи 0 14 001a 0C01 0063 CMPIB #99,%D1 | Не, само десетици и единици? 15 001e 630E BLSB L2 | Да, прескочи стотиците 16 0020 82FC 0064 DIVUW #100,%D1 | Получи десетиците и единиците в старшите 16 17 0024 0641 0030 ADDI #'0',%D1 | бита, а цифрата на стотиците – в младшите; 18 0028 10C1 MOVEB %D1,(%A0)+ | преобразувай я в ASCII-код и я запиши в низа 19 002a E9C1 1010 BFEXTU %D1{0:16},%D1 | Десетиците и единиците – в младшите 16 бита 20 002e 82FC 000A L2: DIVUW #10,%D1 | Цифрата на единиците – в старшите 16 бита, а 21 0032 0641 0030 ADDI #'0',%D1 | на десетиците – в младшите; преобразувай 22 0036 10C1 MOVEB %D1,(%A0)+ | последната в ASCII-код и я запиши в низа 23 0038 E9C1 1010 BFEXTU %D1{0:16},%D1 | Прехвърли цифрата на единиците в младшите 16 24 003c 0641 0030 L3: ADDI #'0',%D1 | бита, преобразувай я в ASCII-код 25 0040 10C1 MOVEB %D1,(%A0)+ | и я запиши в низа 26 0042 E08A LSRL #8,%D2 | Подготви поредния разделител или терминатор 27 0044 10C2 MOVEB %D2,(%A0)+ | Запиши го в низа; последен ли е този байт? 28 0046 66C6 BNEB L1 | Не – премини към обработка на следващия 29 0048 241F MOVEL (%SP)+,%D2 | Да – възстанови съхранения регистър 30 004a 4E75 RTS | и върни управлението x86 NASM putipstr.s 1 ; Да се напише подпрограма, която да записва от адрес, подаден в регистър EDX, 2 ; низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 ; байтовете точка, получен от IP-адрес (IPv4), подаден в регистър EAX. 4 5 section .text 6 global putipstr,_putipstr ;в GCC декларирай с __attribute__((regparm(3))) 7 putipstr: 8 _putipstr: 9 00000000 57 PUSH EDI 10 00000001 92 XCHG EAX,EDX ; EAX = начален адрес на низа, EDX = IP-адрес 11 00000002 97 XCHG EAX,EDI ; EDI = " " " " " " 12 00000003 B9002E2E2E MOV ECX,'.' << 24 | '.' << 16 | '.' << 8; Разделители и терминатор 13 00000008 C1C208 L1: ROL EDX,8 ; Подготви следващия байт, от старши към младши 14 0000000B 88D0 MOV AL,DL ; Байтът трябва да е в AL заради командата AAM 15 0000000D 3C09 CMP AL,9 ; Само единици ли имаме? 16 0000000F 7614 JBE L3 ; Да, запиши ги направо, без нули пред тях 17 00000011 3C63 CMP AL,99 ; Не, само десетици и единици ли имаме? 18 00000013 7608 JBE L2 ; Да, запиши ги направо, без нула пред тях 19 00000015 D464 AAM 100 ; AH = стотици, AL = десетици и единици 20 00000017 80C430 ADD AH,'0' ; Преобразувай цифрата на стотиците в ASCII-код 21 0000001A 8827 MOV [EDI],AH ; и я запиши в низа 22 0000001C 47 INC EDI ; Укажи към следващия символ 23 0000001D D40A L2: AAM ; AH = десетици, AL = единици 24 0000001F 80C430 ADD AH,'0' ; Преобразувай цифрата на десетиците " " " 25 00000022 8827 MOV [EDI],AH ; и я запиши в низа 26 00000024 47 INC EDI ; Укажи към следващия символ 27 00000025 0430 L3: ADD AL,'0' ; Преобразувай единиците в ASCII-код 28 00000027 C1E908 SHR ECX,8 ; Последен байт? 29 0000002A 88CC MOV AH,CL ; (Подготви разделителя като следващ символ 30 0000002C 66AB STOSW ; и запиши единиците и разделителя в низа) 31 0000002E 75D8 JNZ L1 ; Не, премини към обработка на следващия байт 32 00000030 5F POP EDI ; Да, възстанови EDI (GCC изисква да се запази) 33 00000031 C3 RET ; Върни се в извикващата програма ARM GAS putipstr.s page 1 1 // Да се напише подпрограма, която да записва от адрес, подаден в регистър R1, 2 // низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 // байтовете точка, получен от IP-адрес (IPv4), подаден в регистър R0. 4 5 .global putipstr 6 putipstr: 7 0000 30402DE9 STMFD SP!,{R4,R5,LR} //Съхрани използваните регистри (ARM IHI 0042F) 8 0004 50209FE5 LDR R2,='.' << 24 |'.' << 16 | '.' << 8 9 0008 203CA0E1 L1: MOV R3,R0,LSR #24 // Зареди следващ байт (от старши към младши) 10 000c 0004A0E1 MOV R0,R0,LSL #8 // Измести IP-адреса с 1 байт наляво 11 0010 090053E3 CMP R3,#9 // Само единици ли имаме? 12 0014 0400009A BLS L2 // Да, запиши ги направо, без нули пред тях 13 0018 630053E3 CMP R3,#99 // Не, само десетици и единици ли имаме? 14 001c 6440A083 MOVHI R4,#100 // Не, получи и запиши цифрите на стотиците 15 0020 0700008B BLHI DIGIT 16 0024 0A40A0E3 MOV R4,#10 // Направи същото и с десетиците 17 0028 050000EB BL DIGIT 18 002c 303083E2 L2: ADD R3,R3,#'0' // Преобразувай цифрата на единиците в ASCII 19 0030 0130C1E4 STRB R3,[R1],#1 // Запиши ASCII-кода на единиците 20 0034 2224B0E1 MOVS R2,R2,LSR #8 // Последен байт? 21 0038 0120C1E4 STRB R2,[R1],#1 // (Запиши разделителя или терминатора в низа) 22 003c F1FFFF1A BNE L1 // Не: премини към обработка на следващия байт 23 0040 3080BDE8 LDMFD SP!,{R4,R5,PC} //Да: възстанови регистрите, върни управлението 24 25 0044 13F435E7 DIGIT: UDIV R5,R3,R4 // R5 = поредната цифра 26 0048 950404E0 MUL R4,R5,R4 27 004c 043043E0 SUB R3,R3,R4 // R3 = следващите цифри във вид на остатък 28 0050 305085E2 ADD R5,R5,#'0' // Преобразувай цифрата в ASCII-код 29 0054 0150C1E4 STRB R5,[R1],#1 // и я запиши в низа 30 0058 1EFF2FE1 BX LR 30 002E2E2E ARC GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r1, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър r0. 4 5 .global putipstr 6 putipstr: 7 0000 C342 2E2E 002E MOV_S r2,'.' << 24 |'.' << 16 | '.' << 8 8 0006 4128 0306 L1: LSR r3,r0,24 # Зареди следващ байт (от старши към младши) 9 000a 08B8 ASL_S r0,r0,8 # Измести IP-адреса с 1 байт наляво 10 000c 2D0B 9402 BRLS r3,9,L3 # Само единици? Запиши ги без нули пред тях 11 0010 1B0E C570 0000 6300 BRLS r3,99,L2 # Не, само десетици и единици ли имаме? 12 0018 052B 8C0F 0000 6400 DIVU r12,r3,100 # Не, r12 = цифрата на стотиците 13 0020 892B 0109 REMU r3,r3,100 # r3 = следващите цифри във вид на остатък 14 0024 30E4 ADD_S r12,r12,'0' # Преобразувай цифрата на стотиците в ASCII-код 15 0026 0119 1203 STB.AB r12,[r1,1] # и го запиши в низа 16 002a 452B 8C02 L2: DIVU r12,r3,10 # r12 = цифрата на десетиците 17 002e 492B 8302 REMU r3,r3,10 # r3 = цифрата на единиците във вид на остатък 18 0032 30E4 ADD_S r12,r12,'0' # Преобразувай цифрата на десетиците в ASCII- 19 0034 0119 1203 STB.AB r12,[r1,1] # код и го запиши в низа 20 0038 30E3 L3: ADD_S r3,r3,'0' # Преобразувай цифрата на единиците " " " 21 003a 0119 D200 STB.AB r3,[r1,1] # Запиши ASCII-кода на единиците 22 003e 412A 0282 LSR.F r2,r2,8 # Последен байт? 23 0042 0119 9200 STB.AB r2,[r1,1] # (Запиши разделителя или терминатора в низа) 24 0046 E1F5 BNE_S L1 # Не: премини към обработка на следващия байт 25 0048 E07E J_S [blink] # Да: върни управлението PPC GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r4, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър r3. 4 5 .global putipstr 6 putipstr: 7 0000 7D2802A6 mflr r9 # Съхрани lr, защото bl ще го промени! 8 0004 3884FFFF addi r4,r4,-1 # Компенсирай преинкрементната адресация 9 0008 3CA02E2E lis r5,'.' << 8 | '.' 10 000c 38A52E00 addi r5,r5,'.' << 8 # Подготви разделителите и терминатора ('\0') 11 0010 5466463E L1: rlwinm r6,r3,8,24,31 # Зареди следващ байт (от старши към младши) 12 0014 5463402E slwi r3,r3,8 # Измести IP-адреса с 1 байт наляво 13 0018 28060009 cmplwi r6,9 # Само единици ли имаме? 14 001c 40810018 ble L2 # Да, запиши ги направо, без нули пред тях 15 0020 28060063 cmplwi r6,99 # Има ли стотици? 16 0024 38E00064 li r7,100 # (подготви делителя) 17 0028 41810029 bgtl Digit # Ако да, запиши първо тях 18 002c 38E0000A li r7,10 # Направи същото и с десетиците 19 0030 48000021 bl Digit 20 0034 38C60030 L2: addi r6,r6,'0 # Преобразувай цифрата на единиците в ASCII 21 0038 9CC40001 stbu r6,1(r4) # и я запиши в низа, обновявайки указателя 22 003c 54A5C23F srwi. r5,r5,8 # Последен байт? 23 0040 9CA40001 stbu r5,1(r4) # (Запиши разделителя или терминатора в низа) 24 0044 4082FFCC bne L1 # Не, премини към обработка на следващия байт 25 0048 7D2803A6 mtlr r9 # Да, възстанови lr 26 004c 4E800020 blr # и върни управлението 27 28 0050 7D063B96 Digit: divwu r8,r6,r7 # r8 = поредната цифра 29 0054 7CE839D6 mullw r7,r8,r7 30 0058 7CC73050 subf r6,r7,r6 # r6 = следващите цифри във вид на остатък 31 005c 39080030 addi r8,r8,'0 # Преобразувай цифрата в ASCII-код 32 0060 9D040001 stbu r8,1(r4) # и я запиши в низа 33 0064 4E800020 blr SPARC GAS putipstr.s page 1 1 ! Да се напише подпрограма, която да записва от адрес, подаден в регистър %o1, 2 ! низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 ! байтовете точка, получен от IP-адрес (IPv4), подаден в регистър %o0. 4 5 .global putipstr 6 putipstr: 7 0000 8210000F mov %o7,%g1 ! Съхрани %o7, защото „call“ ще го промени! 8 0004 150B8B8B set '.' << 24 |'.' << 16 | '.' << 8,%o2 8 9412A200 9 000c 97322018 L1: srl %o0,24,%o3 ! Зареди следващ байт (от старши към младши) 10 0010 912A2008 sll %o0,8,%o0 ! Измести IP-адреса с 1 байт наляво 11 0014 80A2E009 cmp %o3,9 ! Само единици ли имаме? 12 0018 08800008 bleu L3 ! Да, запиши ги направо, без нули пред тях 13 001c 80A2E063 cmp %o3,99 ! Има ли стотици? 14 0020 08800004 bleu L2 ! Не, прескочи стотиците 15 0024 9A102064 mov 100,%o5 ! (подготви делителя; изпълнява се преди bleu) 16 0028 4000000D call Digit ! Да, запиши първо тях 17 002c 01000000 nop 18 0030 4000000B L2: call Digit ! Направи същото и с десетиците, 19 0034 9A10200A mov 10,%o5 ! („mov“ се изпълнява преди „call“) 20 0038 40000009 L3: call Digit ! и с единиците 21 003c 9A102001 mov 1,%o5 ! („call“ се изпълнява след „mov“) 22 0040 9532A008 srl %o2,8,%o2 ! Подготви следващия разделител или терминатор 23 0044 80A28000 cmp %o2,%g0 ! Последен байт? 24 0048 D42A4000 stb %o2,[%o1] ! (запиши разделителя или терминатора в низа) 25 004c 12BFFFF0 bne L1 ! Не - премини към обработка на следващия байт 26 0050 92026001 add %o1,1,%o1 ! (обнови указателя; изпълнява се преди „bne“) 27 0054 81C06008 jmpl %g1+8,%g0 ! Да - върни се в извикващата програма 28 0058 01000000 nop 29 30 005c 9872C00D Digit: udiv %o3,%o5,%o4 ! %o4 = поредната цифра 31 0060 9A53000D umul %o4,%o5,%o5 32 0064 9622C00D sub %o3,%o5,%o3 ! %o3 = следващите цифри във вид на остатък 33 0068 98032030 add %o4,'0',%o4 ! Преобразувай цифрата в ASCII-код 34 006c D82A4000 stb %o4,[%o1] ! и я запиши в низа 35 0070 81C3E008 retl ! („add“ се изпълнява преди „retl“) 36 0074 92026001 add %o1,1,%o1 ! Обнови указателя MIPS GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър $5, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър $4. 4 5 .ent putipstr 6 .global putipstr 7 putipstr: 8 0000 03E05021 MOVE $10,$31 # Съхрани lr, защото BAL ще го промени! 9 0004 240B0009 LI $11,9 # Подготви най-голямото едноцифрено 10 0008 240C0063 LI $12,99 # и най-голямото двуцифрено число за сравнение 11 000c 3C062E2E 34C62E00 LA $6,'.' << 24 |'.' << 16 | '.' << 8 12 0014 7C873E00 L1: EXT $7,$4,24,8 # Зареди следващ байт (от старши към младши) 13 0018 00042200 SLL $4,$4,8 # Измести IP-адреса с 1 байт наляво 14 001c 0167082A 10200008 00000000 BLE $7,$11,L3 # Само единици? Запиши ги без нули пред тях 15 0028 0187082A 10200003 00000000 BLE $7,$12,L2 # Няма стотици? " " " " " " " 16 LI $8,100 # Получи и запиши цифрите на стотиците 17 0034 0411000B 24080064 BAL Digit 18 L2: LI $8,10 # Направи същото и с десетиците, 19 003c 04110009 2408000A BAL Digit 20 L3: LI $8,1 # и с единиците 21 0044 04110007 24080001 BAL Digit 22 004c 00063202 SRL $6,$6,8 # Последен байт? 23 0050 A0A60000 SB $6,0($5) # (Запиши разделителя или терминатора в низа 24 ADDIU $5,$5,1 # и обнови адреса) 25 0054 14C0FFEF 24A50001 BNE $6,$0,L1 # Не, премини към обработка на следващия байт 26 005c 01400008 00000000 JR $10 # Да, върни управлението 27 28 0064 15000002 00E8001B 0007000D Digit: DIVU $7,$8 # Раздели байта на теглото на поредната цифра 28 00003812 29 0074 00004812 MFLO $9 # Частното е поредната цифра, 30 0078 00003810 MFHI $7 # а остатъкът - това са следващите цифри 31 007c 25290030 ADDIU $9,$9,'0' # Преобразувай цифрата в ASCII-код 32 0080 A0A90000 SB $9,0($5) # и я запиши в низа 33 ADDIU $5,$5,1 # Обнови адреса 34 0084 03E00008 24A50001 JR $31 35 008c 00000000 .end putipstr RISC-V GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър a1, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър a0. 4 5 .global putipstr 6 putipstr: 7 0000 A548 LI a7,9 # Подготви най-голямото едноцифрено 8 0002 93023006 LI t0,99 # и най-голямото двуцифрено число за сравнение 9 0006 37362E2E 130606E0 LA a2,'.' << 24 |'.' << 16 | '.' << 8 10 000e 93568501 L1: SRLI a3,a0,24 # Зареди следващ байт (от старши към младши) 11 0012 2205 SLLI a0,a0,8 # Измести IP-адреса с 1 байт наляво 12 0014 63DBD800 BLE a3,a7,L3 # Само единици? Запиши ги без нули пред тях 13 0018 63D6D200 BLE a3,t0,L2 # Няма стотици? " " " " " " " 14 001c 13074006 LI a4,100 # Получи и запиши цифрите на стотиците 15 0020 6F08C001 JAL a6,Digit 16 0024 2947 L2: LI a4,10 # Направи същото и с десетиците, 17 0026 6F086001 JAL a6,Digit 18 002a 0547 L3: LI a4,1 # и с единиците 19 002c 6F080001 JAL a6,Digit 20 0030 2182 SRLI a2,a2,8 # Последен байт? 21 0032 2380C500 SB a2,0(a1) # (Запиши разделителя или терминатора в низа 22 0036 8505 ADDI a1,a1,1 # и обнови адреса) 23 0038 79FA BNEZ a2,L1 # Не, премини към обработка на следващия байт 24 003a 8280 RET # Да, върни управлението 25 26 003c B3D7E602 Digit: DIVU a5,a3,a4 # Раздели байта на теглото на поредната цифра 27 0040 B3F6E602 REMU a3,a3,a4 # Частно = текущата цифра, остатък = следващите 28 0044 93870703 ADDI a5,a5,'0' # Преобразувай цифрата в ASCII-код 29 0048 2380F500 SB a5,0(a1) # и я запиши в низа 30 004c 8505 ADDI a1,a1,1 # Обнови адреса 31 004e 0288 JR a6 Nios II GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r5, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър r4. 4 5 .global putipstr 6 putipstr: 7 0000 3A881BF8 MOV r13,ra # Съхрани ra, защото CALL ще го промени! 8 0004 5402C002 MOVUI r11,9 # Подготви най-голямото едноцифрено 9 0008 D4180003 MOVUI r12,99 # и най-голямото двуцифрено число за сравнение 10 000c B48B8B01 04808B31 MOVIA r6,'.' << 24 |'.' << 16 | '.' << 8 11 0014 3AD60E20 L1: SRLI r7,r4,24 # Зареди следващ байт (от старши към младши) 12 0018 3A920820 SLLI r4,r4,8 # Измести IP-адреса с 1 байт наляво 13 001c 0E05C059 BLE r7,r11,L3 # Само единици? Запиши ги без нули пред тях 14 0020 0E02C061 BLE r7,r12,L2 # Няма стотици? " " " " " " " 15 0024 14190002 MOVUI r8,100 # Получи и запиши цифрите на стотиците 16 0028 00000000 CALL Digit 17 002c 94020002 L2: MOVUI r8,10 # Направи същото и с десетиците, 18 0030 00000000 CALL Digit 19 0034 54000002 L3: MOVUI r8,1 # и с единиците 20 0038 00000000 CALL Digit 21 003c 3AD20C30 SRLI r6,r6,8 # Последен байт? 22 0040 05008029 STB r6,(r5) # (Запиши разделителя или терминатора в низа 23 0044 44004029 ADDI r5,r5,1 # и обнови адреса) 24 0048 1EF23F30 BNE r6,r0,L1 # Не, премини към обработка на следващия байт 25 004c 3A680068 JMP r13 # Да, върни управлението 26 27 0050 3A20133A Digit: DIVU r9,r7,r8 # Раздели байта на теглото на поредната цифра 28 0054 3A381D4A MUL r14,r9,r8 # Намери остатъка, в който са следващите цифри 29 0058 3AC88F3B SUB r7,r7,r14 30 005c 040C404A ADDI r9,r9,'0' # Преобразувай цифрата в ASCII-код 31 0060 0500402A STB r9,(r5) # и я запиши в низа 32 0064 44004029 ADDI r5,r5,1 # Обнови адреса 33 0068 3A2800F8 RET Xtensa GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър a3, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър a2. 4 5 .global putipstr 6 putipstr: 7 0000 AD00 MOV a10,a0 # Съхрани a0, защото CALL0 ще го промени! 8 0002 92A064 MOVI a9,100 # Подготви число за сравнение 9 0005 410000 MOVI a4,'.' << 24 |'.' << 16 | '.' << 8 10 0008 205875 L1: SRLI a5,a2,24 # Зареди следващ байт (от старши към младши) 11 000b 802211 SLLI a2,a2,8 # Измести IP-адреса с 1 байт наляво 12 000e B6950D BLTUI a5,10,L3 # Само единици? Запиши ги без нули пред тях 13 0011 973505 BLTU a5,a9,L2 # Няма стотици? " " " " " " " 14 0014 62A064 MOVI a6,100 # Получи и запиши цифрите на стотиците 15 0017 C50100 CALL0 Digit 16 001a 0CA6 L2: MOVI a6,10 # Направи същото и с десетиците, 17 001c 450100 CALL0 Digit 18 001f 0C16 L3: MOVI a6,1 # и с единиците 19 0021 050100 CALL0 Digit 20 0024 404841 SRLI a4,a4,8 # Последен байт? 21 0027 424300 S8I a4,a3,0 # (Запиши разделителя или терминатора в низа 22 002a 1B33 ADDI a3,a3,1 # и обнови адреса) 23 002c 5684FD BNEZ a4,L1 # Не, премини към обработка на следващия байт 24 002f A00A00 JX a10 # Да, върни управлението 25 26 0032 0000 .align 4 27 0034 6075C2 Digit: QUOU a7,a5,a6 # Раздели байта на теглото на поредната цифра 28 0037 6055E2 REMU a5,a5,a6 # Частно = текущата цифра, остатък = следващите 29 003a 72C730 ADDI a7,a7,'0' # Преобразувай цифрата в ASCII-код 30 003d 724300 S8I a7,a3,0 # и я запиши в низа 31 0040 1B33 ADDI a3,a3,1 # Обнови адреса 32 0042 0DF0 RET 88K GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r3, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър r2. 4 5 .global _putipstr 6 0000 F5015800 _putipstr: 7 0004 5C802E2E or r8,r1,r0 # Съхрани r1, защото „call“ ще го промени! 8 0008 60842E00 or.u r4,r0,('.' << 8) + '.' 9 000c F0A29818 addu r4,r4,'.' << 8 # Подготви разделителите и терминатора ('\0') 10 0010 F042A008 L1: extu r5,r2,0<24> # Зареди следващ байт (от старши към младши) 11 0014 7D250009 mak r2,r2,0<8> # Измести IP-адреса с 1 байт наляво 12 0018 D9290007 cmp r9,r5,9 # Само единици ли имаме? 13 001c 7D250063 bb1 ls,r9,L3 # Да, запиши ги направо, без нули пред тях 14 0020 58E00064 cmp r9,r5,99 # Има ли стотици? 15 0024 D9290002 or r7,r0,100 # (подготви делителя) 16 0028 C800000A bb1 ls,r9,L2 # Не, прескочи стотиците 17 002c 58E0000A bsr Digit # Да, запиши първо тях 18 0030 C8000008 L2: or r7,r0,10 19 0034 58E00001 bsr Digit # Направи същото и с десетиците, 20 0038 C8000006 L3: or r7,r0,1 21 003c F0849808 bsr Digit # и с единиците 22 0040 F4832C00 extu r4,r4,0<8> # Подготви следващия разделител или терминатор 23 0044 60630001 st.b r4,r3,r0 # Запиши разделителя или терминатора в низа 24 0048 E9A4FFF1 addu r3,r3,1 # Обнови указателя. Последен байт? 25 004c F400C008 bcnd ne0,r4,L1 # Не - премини към обработка на следващия байт 26 jmp r8 # Да - върни се в извикващата програма 27 0050 F4C56807 28 0054 F4E66C07 Digit: divu r6,r5,r7 # r6 = поредната цифра 29 0058 F4A56407 mul r7,r6,r7 30 005c 60C60030 subu r5,r5,r7 # r5 = следващите цифри във вид на остатък 31 0060 F4C32C00 addu r6,r6,'0' # Преобразувай цифрата в ASCII-код 32 0064 60630001 st.b r6,r3,r0 # и я запиши в низа 33 0068 F400C001 addu r3,r3,1 # Обнови указателя jmp r1 Or1k GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър R4, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър R3. 4 5 .global putipstr 6 putipstr: 7 0000 E1690004 L.OR R11,LR,R0 # Съхрани LR, защото „L.JAL“ ще го промени! 8 0004 18A02E2E L.MOVHI R5,'.' << 8 |'.'# Разделители 9 0008 A8A52E00 L.ORI R5,R5,'.' << 8 # Разделител и терминатор 10 000c B8C30058 L1: L.SRLI R6,R3,24 # Зареди следващ байт (от старши към младши) 11 0010 B8630008 L.SLLI R3,R3,8 # Измести IP-адреса с 1 байт наляво 12 0014 BCA60009 L.SFLEUI R6,9 # Само единици ли имаме? 13 0018 10000008 L.BF L3 # Да, запиши ги направо, без нули пред тях 14 001c BCA60063 L.SFLEUI R6,99 # Има ли стотици? 15 0020 10000004 L.BF L2 # Не, прескочи стотиците 16 0024 A9000064 L.ORI R8,R0,100 # (подготви делителя; изпълн. се преди „L.BF“!) 17 0028 0400000D L.JAL Digit # Да, запиши първо тях 18 002c 15000000 L.NOP 0 19 0030 0400000B L2: L.JAL Digit # Направи същото и с десетиците, 20 0034 A900000A L.ORI R8,R0,10 # („L.ORI“ се изпълнява преди „L.JAL“!) 21 0038 04000009 L3: L.JAL Digit # и с единиците 22 003c A9000001 L.ORI R8,R0,1 # („L.JAL“ се изпълнява след „L.ORI“!) 23 0040 B8A50048 L.SRLI R5,R5,8 # Подготви следващия разделител или терминатор 24 0044 E4050000 L.SFEQ R5,R0 # Последен байт? 25 0048 D8042800 L.SB 0(R4),R5 # (запиши разделителя или терминатора в низа) 26 004c 0FFFFFF0 L.BNF L1 # Не - премини към обработка на следващия байт 27 0050 9C840001 L.ADDI R4,R4,1 #(обнови указателя; изпълнява се преди „L.BNF“) 28 0054 44005800 L.JR R11 # Да - върни се в извикващата програма 29 0058 15000000 L.NOP 0 30 31 005c E0E6430A Digit: L.DIVU R7,R6,R8 # R7 = поредната цифра 32 0060 E107430B L.MULU R8,R7,R8 33 0064 E0C64002 L.SUB R6,R6,R8 # R6 = следващите цифри във вид на остатък 34 0068 9CE70030 L.ADDI R7,R7,'0' # Преобразувай цифрата в ASCII-код 35 006c D8043800 L.SB 0(R4),R7 # и я запиши в низа 36 0070 44004800 L.JR LR # („L.ADDI“ се изпълнява преди „L.JR“!) 37 0074 9C840001 L.ADDI R4,R4,1 # Обнови указателя Xilinx MicroBlaze GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър R6, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър R5. 4 5 .global putipstr 6 putipstr: 7 0000 2E2E00B0 002EE0A0 ORI R7,R0,'.' << 24 |'.' << 16 | '.' << 8# Разделители и терм. '\0' 8 0008 18000565 L1: BSRLI R8,R5,24 # Зареди следващ байт (от старши към младши) 9 000c 0804A564 BSLLI R5,R5,8 # Измести IP-адреса с 1 байт наляво 10 0010 F7FF2821 ADDI R9,R8,-9 # Само единици ли имаме? 11 0014 1C0069BC BLEI R9,L3 # Да, запиши ги направо, без нули пред тях 12 0018 9DFF2821 ADDI R9,R8,-99 # Има ли стотици? 13 001c 0C0069BC BLEI R9,L2 # Не, прескочи стотиците 14 0020 300094B8 BRLID R4,Digit # Да, запиши първо тях 15 0024 640020A1 ORI R9,R0,100 # Подготви делителя (изпълн. се преди „BRLID“!) 16 0028 280094B8 L2: BRLID R4,Digit # Направи същото и с десетиците, 17 002c 0A0020A1 ORI R9,R0,10 # (изпълнява се преди „BRLID“!) 18 0030 200094B8 L3: BRLID R4,Digit # и с единиците 19 0034 010020A1 ORI R9,R0,1 # Изпълнява се преди „BRLID“! 20 0038 0800E764 BSRLI R7,R7,8 # Последен байт? 21 003c 0000E6D0 SB R7,R6,R0 # (Запиши разделителя или терминатора в низа, 22 0040 0100C620 ADDI R6,R6,1 # обнови указателя) 23 0044 C4FF27BC BNEI R7,L1 # Не, премини към обработка на следващия байт 24 0048 08000FB6 RTSD R15,8 # и върни управлението 25 004c 00000080 NOP 26 27 0050 02406948 Digit: IDIVU R3,R9,R8 # R3 = поредната цифра 28 0054 00482341 MUL R9,R3,R9 29 0058 00400905 RSUB R8,R9,R8 # R8 = следващите цифри във вид на остатък 30 005c 30006320 ADDI R3,R3,'0' # Преобразувай цифрата в ASCII-код 31 0060 000066D0 SB R3,R6,R0 # и я запиши в низа 32 0064 080004B6 RTSD R4,8 33 0068 0100C620 ADDI R6,R6,1 # Обнови указателя (изпълнява се преди „RTSD“!) HPPA GAS putipstr.s page 1 1 ; Да се напише подпрограма, която да записва от адрес, подаден в регистър %R25, 2 ; низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 ; байтовете точка, получен от IP-адрес (IPv4), подаден в регистър %R26. 4 5 .text 6 ZDELIM .equ '. << 24 |'. << 16 | '. << 8 7 .import UDIV,code 8 .global putipstr 9 putipstr: 10 0000 081A0256 COPY %R26,%R22 ; Съхрани IP-адреса (%R26 е делител на UDIV) и 11 0004 0802025F COPY %R2,%R31 ; адреса на връщане (%R2 се използва от UDIV) 12 0008 22F1D5C4 LDIL L%ZDELIM,%R23 ; %R22: IP-адр., %R25: адр. на низа, %R24: байт 13 000c 36F70C00 LDO R%ZDELIM(%R23),%R23; Подготви 3 разделителя и 1 терминатор (0) 14 0010 D2D818F8 L1: EXTRU %R22,7,8,%R24 ; Зареди следващ байт (от старши към младши) 15 0014 8F14A058 COMIBF,<<= 10,%R24,L3 ; Само единици? Запиши ги направо, без водещи 0 16 0018 D6D60908 ZDEP %R22,23,24,%R22 ; Измести адр.с байт вляво (изп.се преди COMIBF 17 001c E8400000 BL UDIV,%R2 ; Раздели байта на 100: %R28: частно, %R29: ост 18 0020 341A00C8 LDI 100,%R26 ; Делител (изп. се преди BL, делимото е в %R24) 19 0024 87802010 COMIBT,= 0,%R28,L2 ; Само десетици и единици? Прескочи стотиците 20 0028 081D0258 COPY %R29,%R24 ; Остатъкът ще бъде делимо (изп.се преди COMIBT 21 002c D7861C9E DEPI 3,27,2,%R28 ; Преобразувай цифрата на стотиците в ASCII-код 22 0030 0F3C1222 STBS,MA %R28,1(%R25) ; Запиши ASCII-кода в низа, обновявайки адреса 23 0034 E8400000 L2: BL UDIV,%R2 ; Получи десетиците и единиците по същия начин 24 0038 341A0014 LDI 10,%R26 ; Делител за десетиците (изпълнява се преди BL) 25 003c 081D0258 COPY %R29,%R24 ; Остатъкът е цифрата на единиците, а 26 0040 D7861C9E DEPI 3,27,2,%R28 ; частното – на десетиците. Преобразувай в ASCII 27 0044 0F3C1222 STBS,MA %R28,1(%R25) ; и запиши в низа, обновявайки после и адреса му 28 0048 D7061C9E L3: DEPI 3,27,2,%R24 ; Постъпи по същия начин 29 004c 0F381222 STBS,MA %R24,1(%R25) ; с цифрата на единиците 30 0050 D2E00AF7 SHD %R0,%R23,8,%R23 ; Подготви следващ разделител или терминатор... 31 0054 8AE03F6D COMBF,= 0,%R23,L1 ;(не е 0? Отиди на следващия; изп.се след STBS) 32 0058 0F371222 STBS,MA %R23,1(%R25) ; ...и го запиши в низа, обновявайки и адреса 33 005c EBE0C002 BV,N (%R31) ; Адресът на връщане е бил съхранен в %R31 UNDEFINED SYMBOLS UDIV Renesas / SuperH SH GAS Little Endian putipstr.s page 1 1 ! Да се напише подпрограма, която да записва от адрес, подаден в регистър R5, 2 ! низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 ! байтовете точка, получен от IP-адрес (IPv4), подаден в регистър R4. 4 5 .global putipstr 6 putipstr: 7 0000 224F STS.L PR,@-SP ! Съхрани PR, защото „BSR“ ще го промени! 8 0002 2800 CLRMAC ! MACH = 0 (старша дума на делимото за „UDIV“) 9 0004 13D6 MOV.L ZDELIM,R6 ! Подготви 3 разделителя и 1 терминатор (0) 10 0006 4367 MOV R4,R7 ! Съхрани IP-адреса (R4 е делител за „UDIV“) 11 0008 7363 L1: MOV R7,R3 12 000a 2943 SHLR16 R3 ! Зареди следващ байт (от старши към младши) 13 000c 1943 SHLR8 R3 14 000e 1847 SHLL8 R7 ! Измести IP-адреса с 1 байт наляво 15 0010 0AE4 MOV #10,R4 16 0012 4233 CMP/HS R4,R3 ! Само единици ли имаме? 17 0014 068B BF L3 ! Да, запиши ги направо, без нули пред тях 18 0016 64E4 MOV #100,R4 19 0018 4233 CMP/HS R4,R3 ! Има ли стотици? 20 001a 018B BF L2 ! Не, прескочи стотиците 21 001c 0CB0 BSR Digit ! Да, запиши първо тях 22 001e 0900 NOP 23 0020 0AB0 L2: BSR Digit ! Направи същото и с десетиците, 24 0022 0AE4 MOV #10,R4 ! („MOV“ се изпълнява преди „BSR“) 25 0024 08B0 L3: BSR Digit ! и с единиците 26 0026 01E4 MOV #1,R4 ! („BSR“ се изпълнява след „MOV“) 27 0028 1946 SHLR8 R6 ! Подготви следващия разделител или терминатор 28 002a 6025 MOV.B R6,@R5 ! Запиши разделителя или терминатора в низа 29 002c 0175 ADD #1,R5 ! Обнови указателя 30 002e 1546 CMP/PL R6 ! Последен байт? 31 0030 EA89 BT L1 ! Не - премини към обработка на следващия байт 32 0032 264F LDS.L @SP+,PR ! Да - възстанови PR 33 0034 0B00 RTS ! и се върни в извикващата програма 34 0036 0900 NOP 35 36 0038 224F Digit: STS.L PR,@-SP ! Съхрани PR, защото „JSR“ ще го промени! 37 003a 07D1 MOV.L UDIVPTR,R1 ! Подготви адреса на функцията за делене „UDIV“ 38 003c 0B41 JSR @R1 ! R0 = поредната цифра (изпълн. се след „LDS“) 39 003e 1A43 LDS R3,MACL ! „UDIV“ иска делимо в MACH:MACL и делител в R4 40 0040 1A03 STS MACL,R3 ! Възстанови делимото 41 0042 264F LDS.L @SP+,PR ! Възстанови PR 42 0044 4700 MUL.L R4,R0 43 0046 1A01 STS MACL,R1 ! R1 = произведението на делителя и частното 44 0048 1833 SUB R1,R3 ! R3 = следващите цифри във вид на остатък 45 004a 3070 ADD #'0',R0 ! Преобразувай цифрата в ASCII-код 46 004c 0025 MOV.B R0,@R5 ! и я запиши в низа 47 004e 0B00 RTS 48 0050 0175 ADD #1,R5 ! Обнови указателя (изпълнява се преди „RTS“) 49 0052 0900 .align 2 50 0054 002E2E2E ZDELIM: .long '.' << 24 |'.' << 16 | '.' << 8 51 0058 00000000 UDIVPTR:.long UDIV UNDEFINED SYMBOLS UDIV GAS for CRIS putipstr.s page 1 1 ; Да се напише подпрограма, която да записва от адрес, подаден в регистър R11, 2 ; низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 ; байтовете точка, получен от IP-адрес (IPv4), подаден в регистър R10. 4 5 .global putipstr 6 putipstr: 7 0000 79B6 MOVE $SRP,$R9 ; Съхрани SRP, защото „BSR“ ще го промени! 8 0002 6AD6 MOVE.D $R10,$R13 ; Освободи R10 и R11 за извикването на „UDIV16“ 9 0004 6BF6 MOVE.D $R11,$R15 ; R13 = IP-адрес, R15 = адрес на буфера за низа 10 0006 6FCE002E 2E2E MOVE.D '.' << 24 |'.' << 16 | '.' << 8,$R12 11 000c 6DA6 L1: MOVE.D $R13,$R10 12 000e F8A3 LSRQ 24,$R10 ; Зареди следващ байт (от старши към младши) 13 0010 C8D3 LSLQ 8,$R13 ; Измести IP-адреса с 1 байт наляво 14 0012 C9A2 CMPQ 9,$R10 ; Само единици ли имаме? 15 0014 1C80 BLS L3 ; Да, запиши ги направо, без нули пред тях 16 0016 CFAE6300 CMP.B 99,$R10 ; Има ли стотици? 17 001a 0E80 BLS L2 ; Не, прескочи стотиците 18 001c 5FBE6400 MOVE.W 100,$R11 ; (подготви делителя; изпълнява се преди „BSR“) 19 0020 BFBE2600 0000 BSR Digit ; Да, запиши първо тях 20 0026 B005 NOP 21 0028 BFBE1E00 0000 L2: BSR Digit ; Направи същото и с десетиците, 22 002e 4AB2 MOVEQ 10,$R11 ; („MOVEQ“ се изпълнява преди „BSR“) 23 0030 BFBE1600 0000 L3: BSR Digit ; и с единиците 24 0036 41B2 MOVEQ 1,$R11 ; („BSR“ се изпълнява след „MOVEQ“) 25 0038 E8C3 LSRQ 8,$R12 ; Подготви следващия разделител или терминатор 26 003a C0C2 CMPQ 0,$R12 ; Последен байт? 27 003c CFCF MOVE.B $R12,[$R15+] ; (запиши разделителя или терминатора в низа) 28 003e CF20 BNE L1 ; Не - премини към обработка на следващия байт 29 0040 39B6 MOVE $R9,$SRP ; Възстанови SRP (изпълнява се преди „BNE“) 30 0042 F0B9 RET ; Да - върни се в извикващата програма 31 0044 B005 NOP 32 33 0046 BF7E0000 0000 Digit: BAS UDIV16,$MOF ; R10 = поредната цифра, R11 = следващите цифри 34 004c B005 NOP 35 004e 30A2 ADDQ '0',$R10 ; Преобразувай цифрата в ASCII-код 36 0050 CFAF MOVE.B $R10,[$R15+] ; и я запиши в низа 37 0052 F0B9 RET ; (следващата „MOVE“ се изпълнява преди „RET“) 38 0054 6BA60000 MOVE.D $R11,$R10 ; R10 = следващите цифри (остатък от деленето) UNDEFINED SYMBOLS UDIV16 BFIN GAS putipstr.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър R1, 2 # низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 # байтовете точка, получен от IP-адрес (IPv4), подаден в регистър R0. 4 5 .global _putipstr 6 _putipstr: 7 0000 E305 [--SP] = (R7:4, P5:3); # Съхрани R4–R7/P3–P5 (82-000410-03 стр. 1-433) 8 0002 3731 R6 = RETS; # Съхрани адреса на връщане; CALL ще го промени 9 0004 0132 P0 = R1; # Адресът на буфера – в адресен регистър 10 0006 1030 R2 = R0; # Освободи R0 за подпрограмата за делене 11 0008 44E12E2E R4.H = '.' << 8 | '.'; # Старша дума на низа от разделители 12 000c 04E1002E R4.L = '.' << 8; # Младша " " " " " " 13 0010 5560 R5 = 10 (X); # Подготви число за сравнение 14 0012 82C64287 L_1: R3 = R2 >> 24; # Зареди следващ байт (от старши към младши) 15 0016 424F R2 <<= 8; # Измести IP-адреса с 1 байт наляво 16 0018 AB09 CC = R3 < R5 (IU); # Само единици? 17 001a 0A18 IF CC JUMP L_3; # Да, запиши ги без нули пред тях 18 001c 21E16400 R1 = 100 (X); # Не, подготви число за сравнение 19 0020 8B09 CC = R3 < R1 (IU); # Само десетици и единици? 20 0022 0318 IF CC JUMP L_2; # Да, запиши ги без нули пред тях 21 0024 00E30E00 CALL Digit; # Не, получи и запиши в низа стотиците 22 0028 5160 L_2: R1 = 10 (X); # Направи същото и с десетиците 23 002a 00E30B00 CALL Digit; 24 002e 8365 L_3: R3 += '0'; # Преобразувай единиците в ASCII-код 25 0030 039A B [P0++] = R3; # и го запиши в низа 26 0032 444E R4 >>= 8; # Премести следващия разделител или терминатор 27 0034 049A B [P0++] = R4; # в най-младшия байт и го запиши в низа 28 0036 0003 CC = AZ; # Последен байт (терминатор)? 29 0038 ED13 IF !CC JUMP L_1; # Не, премини към обработка на следващия байт 30 003a 3E38 RETS = R6; # Да, възстанови адреса на връщане 31 003c A305 (R7:4, P5:3) = [SP++]; # и съхранените регистри 32 003e 1000 RTS; # Върни управлението 33 34 0040 0330 Digit: R0 = R3; # Делимото трябва да е в R0 (делителят е в R1) 35 0042 3F31 R7 = RETS; # Съхрани адреса на връщане; CALL ще го промени 36 0044 FFE3DEFF CALL _UDIV16; # Раздели байта на теглото на поредната цифра 37 0048 3F38 RETS = R7; # Възстанови адреса на връщане 38 004a C140 R1 *= R0; # Получи произведението на делителя и частното 39 004c CB52 R3 = R3 - R1; # Остатък = делимото − делителя × частното 40 004e 8065 R0 += '0'; # Преобразувай частното (цифрата) в ASCII-код 41 0050 009A B [P0++] = R0; # и го запиши в низа 42 0052 1000 RTS; # Върни остатъка в R3: съдържа следващите цифри UNDEFINED SYMBOLS _UDIV16 Hexagon GAS putipstr.s page 1 1 // Да се напише подпрограма, която да записва от адрес, подаден в регистър R1, 2 // низ тип ASCIIZ в десетичен формат без водещи нули и с разделител между 3 // байтовете точка, получен от IP-адрес (IPv4), подаден в регистър R0. 4 5 .global putipstr 6 putipstr: 7 0000 B878E202 02C00078 R2 = #'.' << 24 | '.' << 16 | '.' << 8 // Разделители и терминатор 8 L1: { R3 = LSR(R0,#24) // Зареди следващ байт (от старши към младши) 9 0008 2358008C 40C8008C R0 = ASL(R0,#8) } // Измести IP-адреса с 1 байт наляво 10 { P0 = CMP.GTU(R3,#9) // Само единици ли имаме? 11 IF (!P0.NEW) JUMP:NT L2 // Да, запиши ги направо, без нули пред тях 12 P1 = CMP.GTU(R3,#99) // Не, само десетици и единици ли имаме? 13 0010 20494311 614C8375 707D2800 24C50078 R4 = #(1 << 32) / 100 + 1 } // R4 = множител за деленето на 100 14 0020 25C443ED R5 = MPYU(R3,R4) // R5 = цифрата на стотиците 15 0024 84CC05E0 R4 = MPYI(R5,#100) //умножението не може да е условно, но не пречи 16 { IF (P1) R3 = SUB(R3,R4) // Не, R3 = следващите цифри във вид на остатък 17 IF (P1) R5 = ADD(R5,#'0')//Преобразувай цифрата на стотиците в ASCII 18 0028 234324FB 05462574 09E3A1AB IF (P1) MEMB(R1++#1) = R5.NEW }// и го запиши в низа 19 0034 66669901 44C30078 R4 = #(1 << 32) / 10 + 1 //Множител за деленето на 10 чрез умножение 20 003C 25C443ED R5 = MPYU(R3,R4) // R5 = цифрата на десетиците 21 0040 44C105E0 R4 = MPYI(R5,#10) // R4 = " " " единиците 22 { R3 = SUB(R3,R4) 23 R5 = ADD(R5,#'0') // Преобразувай цифрата на десетиците в ASCII 24 0044 034324F3 054605B0 08C3A1AB MEMB(R1++#1) = R5.NEW } // и го запиши в низа 25 L2: { R3 = ADD(R3,#'0') // Преобразувай цифрата на единиците в ASCII 26 0050 034603B0 08C3A1AB MEMB(R1++#1) = R3.NEW } // и го запиши в низа 27 { R2 = LSR(R2,#8) // Последен байт? 28 0058 2248028C 08C2A1AB MEMB(R1++#1) = R2.NEW } // (Запиши разделителя или терминатора в низа) 29 0060 D4FF2261 IF (R2!=#0) JUMP:T L1 // Не: премини към обработка на следващия байт 30 0064 00C09F52 JUMPR LR //Да: възстанови регистрите, върни управлението S/390 GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри 2:3 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър 2. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 1711 XR 1,1 # Старшите байтове трябва да са нули 8 0002 1733 XR 3,3 # Започни начисто 9 0004 1755 L1: XR 5,5 # Нов текущ байт - започни натрупването от нулата 10 0006 43102000 L2: IC 1,0(2) # Зареди поредния символ 11 000a A72A0001 AHI 2,1 # Обнови адреса 12 000e A71E0030 CHI 1,'0' # Цифра? 13 0012 A744001C JL L5 # Не, разделител или терминатор е - байтът е готов 14 0016 A71E0039 CHI 1,'9' 15 001a A7240006 JH L3 # Не, провери за буква или разделител 16 001e A71AFFD0 AHI 1,-'0' # Да, преобразувай от ASCII-код в тетрада битове 17 0022 A7F4000F J L4 18 0026 A70800DF L3: LHI 0,~('a-'A') & 0xFF 19 002a 1410 NR 1,0 # Преобразувай евентуална малка буква в главна 20 002c A71E0041 CHI 1,'A' # Главна буква? 21 0030 A744000D JL L5 # Не, разделител е - байтът е готов 22 0034 A71E0046 CHI 1,'F' 23 0038 A7240009 JH L5 # Не, също 24 003c A71AFFC9 AHI 1,10-'A'# Да, преобразувай от ASCII-код в тетрада битове 25 0040 89500004 L4: SLL 5,4 # Направи място за новата шестнадесетична цифра 26 0044 1E51 ALR 5,1 # и я добави към текущата стойност 27 0046 A7F4FFE0 J L2 # Продължи със следващия символ от низа 28 004a 89400008 L5: SLL 4,8 # Измести текущия адрес в 4:3 с 1 байт наляво 29 004e 1803 LR 0,3 30 0050 88000018 SRL 0,24 31 0054 1640 OR 4,0 32 0056 89300008 SLL 3,8 33 005a 1635 OR 3,5 # Запиши текущия байт отдясно 34 005c 8411FFD4 BRXH 1,1,L1 # Край на низа? Ако не, продължи със следващия байт 35 0060 1824 LR 2,4 # Да, върни адреса в 2:3 36 0062 07FE BR 14 ==> id32/getmacst.s <== 1 * Write at the address at 7(4) the MAC-address obtained from an ASCIIZ string 2 * starting at 7(0) -> register 2. The string is in hexadecimal format with a 3 * punctuation mark as a delimiter between the bytes (e.g. 00-0C-76-1F-C5-EB). 4 5 entry getmacst 00000000d 6 getmacst equ * 00000d 5827 0000 7 l 2,0(7) String address 00004d 0733 8 xr 3,3 Start from zeros 00006d 0755 9 L1 xr 5,5 New current byte - start accumularing from 0 00008d D312 0000 10 L2 lb 1,0(2) Load the next character 0000Cd 2621 11 ais 2,1 Update the address 0000Ed C510 0030 12 clhi 1,c'0' A digit? [The "(0)" may be omitted - "as" accepts this] 00012d 4280 8028 0000003Ed 13 bl L5 No, a delimiter or terminator - the byte is ready 00016d C510 003A 14 clhi 1,c':' (The ASCII-code after '9') 0001Ad 2384 00000022d 15 bnls L3 No, check for a letter or delimiter 0001Cd CB10 0030 16 shi 1,c'0' Yes, convert it from ASCII to a BCD nibble 00020d 230B 00000036d 17 bs L4 00022d C410 00DF 18 L3 nhi 1,x'df' ~('a'-'A') No, convert an eventual lower case to upper 00026d C510 0041 19 clhi 1,c'A' Upper case letter? 0002Ad 218A 0000003Ed 20 bls L5 No, it's a delimiter - the byte is ready 0002Cd C510 0047 21 clhi 1,c'G' 00030d 2387 0000003Ed 22 bnls L5 No, ditto 00032d CB10 0037 23 shi 1,c'A'-10 Yes, convert from ASCII to a nibble 00036d 1154 24 L4 slls 5,4 Make room for the new hexadecimal digit 00038d 0A51 25 ar 5,1 and add it to the current value 0003Ad 4300 FFCA 00000008d 26 b L2 Go on with the next character of the string 0003Ed 1148 27 L5 slls 4,8 Shift the current MAC-address in registers 4:3 left 00040d 0803 28 lr 0,3 by 1 byte 00042d EC00 0018 29 srl 0,24 00046d 0640 30 or 4,0 00048d 1138 31 slls 3,8 0004Ad 0635 32 or 3,5 Write the current byte from the right 0004Cd 0611 33 or 1,1 Was the last loaded byte a terminator ('\0')? 0004Ed 4230 FFB4 00000006d 34 bnz L1 No, continue with the next byte 00052d 5817 0004 35 l 1,4(7) Yes, store the MAC-address that is in registers 4:3 at 00056d 5041 0000 36 st 4,0(1) the address passed as a second argument to the function 0005Ad 5031 0004 37 st 3,4(1) 0005Ed 030F 38 br 15 VAX GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри R1:R0 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в AP(4) -> R2. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global _getmacst 6 _getmacst: 7 0000 3C00 .word 0x3C # R2-R5 8 0002 D0AC0452 MOVL 4(AP),R2# Начален адрес на низа 9 0006 7C50 CLRQ R0 # Започни начисто 10 0008 7C53 L1: CLRQ R3 # Нов текущ байт - започни натрупването от нулата 11 000a 9A8255 L2: MOVZBL (R2)+,R5# Зареди поредния символ 12 000d 3D2F0055 2500 ACBW $'0'-1,$0,R5,L4 # Разделител или терминатор? Байтът е готов 13 0013 3D390055 1500 ACBW $'9',$0,R5,L3# Не, цифра? 14 0019 8A2055 BICB2 $'a'-'A',R5 # Не, преобразувай евентуална малка буква в главна 15 001c 3D8F4000 00551400 ACBW $'A'-1,$0,R5,L4# Разделител? Байтът готов! Повтори на следв.ред 16 0024 3D8F4000 8FF9FF55 0A00 ACBW $16+'0',$10-'A'+'0',R5,L4 # Преобраз. буква от ASCII в 2 стъпки 17 002e 823055 L3: SUBB2 $'0',R5 # Цифра: преобразувай я от ASCII-код в двоичнодесетичен 18 0031 7A105355 53 EMUL $16,R3,R5,R3# Добави тетрадата към изместения с 4 б. текущ байт 19 0036 11D2 BRB L2 # Продължи със следващия символ от низа 20 0038 79085050 L4: ASHQ $8,R0,R0# Измести текущия адрес в R1:R0 с 1 байт наляво 21 003c 905350 MOVB R3,R0 # Запиши текущия байт отдясно 22 003f 95A2FF TSTB -1(R2) # Терминатор ('\0') ли е бил последният зареден символ? 23 0042 12C4 BNEQ L1 # Не, продължи със следващия байт 24 0044 04010101 RET # Да, върни MAC-адреса в R1:R0 ==> we32k/getmacst.s <== # Return in registers r0:r1 the MAC-address obtained from an ASCIIZ string # starting at ap(0) -> r7. The string is in a hexadecimal format with a # punctuation mark as a delimiter between the bytes (e.g. 00-0C-76-1F-C5-EB). section .text .globl getmacst getmacst() getmacst: 0: 10 47 SAVE %r7 #"AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 47 MOVW 0(%ap),%r7 # Programming Manual", pp. 6-13, 6-14 5: 70 NOP 6: 80 40 CLRW %r0 # Start from zeros 8: 80 41 CLRW %r1 a: 80 48 L1: CLRW %r8 # New current byte - start accumularing from 0 c: 87 57 42 L2: MOVB (%r7),%r2 # Load the next character f: 70 NOP 10: 90 47 INCW %r7 # Update the address 12: 3f 30 42 CMPB &0x30,%r2 # Delimiter or terminator (0x30 = '0')? 15: 5b 27 BLUB L4 # Yes, the byte is ready 17: 3f 39 42 CMPB &0x39,%r2 # No, a digit (0x39 = '9' unsupported by "as")? 1a: 5f 16 BLEUB L3 # Yes, convert it from ASCII 1c: bb 5f df 00 42 ANDB2 &0xDF,%r2 # No, convert an eventual lower case to upper 21: 3f 6f 41 42 CMPB &0x41,%r2 # Upper case letter (0x41 = 'A')? 25: 5b 17 BLUB L4 # No, it's a delimiter - the byte is ready 27: 3f 6f 46 42 CMPB &0x46,%r2 # 0x46 = 'F' 2b: 57 11 BGUB L4 # No, ditto 2d: bf 07 42 SUBB2 &0x41-10-0x30,%r2#'A'-10-'0' Yes, convert from ASCII in 2 steps 30: bf 30 42 L3: SUBB2 &0x30,%r2 # 0x30 = '0' A digit: convert from ASCII to BCD 33: d0 04 48 48 LLSW3 &4,%r8,%r8 # Make room for the new hexadecimal digit 37: 9f 42 48 ADDB2 %r2,%r8 # and add it to the current value 3a: 7b d2 BRB L2 # Go on with the next character of the string 3c: d0 08 40 40 L4: LLSW3 &8,%r0,%r0 # Shift the current MAC address in r0:r1 left 40: d8 18 41 41 ROTW &24,%r1,%r1 # by 1 byte (24-bit right rotate = 8-bit left) 44: c8 07 00 41 40 INSFW &7,&0,%r1,%r0 49: c8 07 00 48 41 INSFW &7,&0,%r8,%r1 # Write the current byte from the right 4e: 2b 42 TSTB %r2 # Was the last loaded byte a terminator ('\0')? 50: 77 ba BNEB L1 # No, continue with the next byte 52: 04 c9 f0 4c MOVAW -16(%fp),%sp RESTORE %r7 # Yes, restore the saved registers (r7,r8) 56: 20 48 POPW %r8 58: 20 47 POPW %r7 5a: 20 49 POPW %fp 5c: 08 RET # and return the MAC address in r0:r1 5d: 70 NOP 5e: 70 NOP 5f: 70 NOP 68K GAS getmacst.s page 1 1 | Да се напише подпрограма, която да връща в регистри D0:D1 MAC-адреса, 2 | получен от низа тип ASCIIZ с начален адрес в SP(4) -> A0. Низът е в 16-ичен 3 | вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 206F 0004 MOVEL 4(%SP),%A0 | Начален адрес на низа 8 0004 48E7 3000 MOVEML %D2-%D3,-(%SP) | GCC изисква D2 и следващите да се съхраняват 9 0008 4280 CLRL %D0 | Започни начисто 10 000a 4281 CLRL %D1 11 000c 4283 L1: CLRL %D3 | Нов текущ байт - започни натрупването от нулата 12 000e 1418 L2: MOVEB (%A0)+,%D2| Зареди поредния символ 13 0010 0C02 0030 CMPIB #'0',%D2| Разделител или терминатор? 14 0014 6524 BLOB L4 | Да, байтът е готов 15 0016 0C02 0039 CMPIB #'9',%D2| Не, цифра? 16 001a 6314 BLSB L3 | Да, преобразувай я от ASCII-код 17 001c 0882 0005 BCLRB #5,%D2 | Не, преобразувай евентуална малка буква в главна 18 0020 0C02 0041 CMPIB #'A',%D2| Главна буква? 19 0024 6514 BLOB L4 | Не, разделител е - байтът е готов 20 0026 0C02 0046 CMPIB #'F',%D2 21 002a 620E BHIB L4 | Не, също 22 002c 0402 0007 SUBIB #'A'-10-'0',%D2| Да, преобразувай от ASCII-код в две стъпки 23 0030 0402 0030 L3: SUBIB #'0',%D2| Цифра: преобразувай я от ASCII-код в двоичнодесетичен 24 0034 E90B LSLB #4,%D3 | Направи място за новата шестнадесетична цифра 25 0036 D602 ADDB %D2,%D3 | и я добави към текущата стойност 26 0038 60D4 BRAB L2 | Продължи със следващия символ от низа 27 003a E188 L4: LSLL #8,%D0 | Измести текущия адрес в D0:D1 с 1 байт наляво 28 003c E199 ROLL #8,%D1 29 003e EFC0 1608 BFINS %D1,%D0{24:8} 30 0042 1203 MOVEB %D3,%D1 | Запиши текущия байт отдясно 31 0044 0C02 0000 CMPIB #0,%D2 | Терминатор ('\0') ли е последният зареден символ? 32 0048 66C2 BNEB L1 | Не, продължи със следващия байт 33 004a 4CDF 000C MOVEML (%SP)+,%D2-%D3 34 004e 4E75 RTS | Да, възстанови регистрите и върни MAC-адреса в D0:D1 x86 NASM getmacst.s 1 ; Да се напише подпрограма, която да връща в регистри EDX:EAX MAC-адреса, 2 ; получен от низа тип ASCIIZ с начален адрес в регистър EAX. Низът е в 16-ичен 3 ; вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB. 4 5 section .text 6 global getmacst,_getmacst; в GCC декларирай с __attribute__((regparm(3))) 7 getmacst: 8 _getmacst: 9 00000000 56 PUSH ESI ; GCC изисква ESI да се съхрани 10 00000001 96 XCHG EAX,ESI ; LODSB работи с ESI 11 00000002 31C9 XOR ECX,ECX ; Започни начисто 12 00000004 B400 L1: MOV AH,0 ; Нов текущ байт - започни натрупването от нулата 13 00000006 AC L2: LODSB ; Зареди поредния символ 14 00000007 3C30 CMP AL,'0' ; Цифра? 15 00000009 7218 JB L5 ; Не, разделител или терминатор е - байтът е готов 16 0000000B 3C39 CMP AL,'9' 17 0000000D 760C JBE L3 ; Да, прескочи проверката за буква 18 0000000F 24DF AND AL,~('a'-'A');Не, преобразувай евентуална малка буква в главна 19 00000011 3C41 CMP AL,'A' ; Главна буква? 20 00000013 720E JB L5 ; Не, разделител е - байтът е готов 21 00000015 3C46 CMP AL,'F' 22 00000017 770A JA L5 ; Не, също 23 00000019 2C07 SUB AL,'A'-10-'0';Да, преобразувай я от ASCII-код в 2 стъпки 24 0000001B 2C30 L3: SUB AL,'0' ; Преобразувай от ASCII-код в тетрада битове 25 0000001D D510 L4: AAD 16 ; Добави я към умножената по 16 текуща стойност 26 0000001F 88C4 MOV AH,AL ; Запази текущата стойност на байта 27 00000021 EBE3 JMP L2 ; Продължи със следващия символ от низа 28 00000023 0FA4CA08 L5: SHLD EDX,ECX,8;Измести текущия адрес в EDX:ECX с 1 байт наляво 29 00000027 C1E108 SHL ECX,8 30 0000002A 88E1 MOV CL,AH ; Запиши текущия байт отдясно 31 0000002C 3C00 CMP AL,0 ; Край на низа? 32 0000002E 75D4 JNZ L1 ; Не, продължи със следващия байт 33 00000030 91 XCHG EAX,ECX ; Да, върни адреса в EDX:EAX 34 00000031 5E POP ESI 35 00000032 C3 RET ARM GAS getmacst.s page 1 1 // Да се напише подпрограма, която да връща в регистри R1:R0 MAC-адреса, 2 // получен от низа тип ASCIIZ с начален адрес в регистър R0. Низът е в 16-ичен 3 // вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 0020A0E3 MOV R2,#0 // Започни начисто 8 0004 0030A0E3 L1: MOV R3,#0 // Нов текущ байт - започни натрупването от нулата 9 0008 01C0D0E4 L2: LDRB R12,[R0],#1//Зареди поредния символ 10 000c 30005CE3 CMP R12,#'0'// Цифра? 11 0010 0900003A BLO L4 // Не, разделител или терминатор е - байтът е готов 12 0014 39005CE3 CMP R12,#'9' 13 0018 30C04C92 SUBLS R12,#'0'// Да, преобразувай от ASCII-код в тетрада битове 14 001c 0400009A BLS L3 15 0020 20C0CCE3 BIC R12,#'a'-'A'//Преобразувай евентуална малка буква в главна 16 0024 41005CE3 CMP R12,#'A'// Главна буква? 17 0028 0300003A BLO L4 // Не, разделител е - байтът е готов 18 002c 46005CE3 CMP R12,#'F' 19 0030 37C04C92 SUBLS R12,#'A'-10//Да, преобразувай от ASCII-код в тетрада битове 20 0034 03328C90 L3: ADDLS R3,R12,R3,LSL #4//Добави я към умножената по 16 текуща стойност 21 0038 F2FFFF9A BLS L2 // Продължи със следващия символ от низа 22 003c 0114A0E1 L4: MOV R1,R1,LSL #8//Измести текущия адрес в R1:R2 с 1 байт наляво 23 0040 221C81E1 ORR R1,R1,R2,LSR #24 24 0044 022483E1 ORR R2,R3,R2,LSL #8 //Запиши текущия байт отдясно 25 0048 00005CE3 CMP R12,#0 // Край на низа? 26 004c ECFFFF1A BNE L1 // Не, продължи със следващия байт 27 0050 0200A0E1 MOV R0,R2 // Да, върни адреса в R1:R0 28 0054 1EFF2FE1 BX LR ARC GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри r1:r0 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър r0. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 4C70 MOV_S r2,0 # Започни начисто 8 0002 6C70 L1: MOV_S r3,0 # Нов текущ байт - започни натрупването от нулата 9 0004 0110 8C04 L2: LDB.AB r12,[r0,1]# Зареди поредния символ 10 0008 2B0C 141C BRLO r12,'0',L5# Разделител или терминатор - байтът е готов 11 000c 0B0C 951E BRHI r12,'9',L3# Провери за буква 12 0010 4224 0C1C SUB r12,r12,'0'# Цифра – преобразувай от ASCII-код в тетрада битове 13 0014 0CF0 B_S L4 14 0016 A5BC L3: BCLR_S r12,r12,5# Преобразувай евентуална малка буква в главна 15 0018 1B0C 841F 0000 4100 BRLO r12,'A',L5# Разделител - байтът е готов 16 0020 130E 0473 0000 4600 BRHI r12,'F',L5# " " " " " " " 17 0028 4224 CC1D SUB r12,r12,'A'-10# Главна буква – преобразувай от ASCII в тетрада 18 002c 746B L4: ASL_S r3,r3,4 # Направи място за новата шестнадесетична цифра 19 002e 9B63 ADD_S r3,r3,r12# и я добави към текущата стойност 20 0030 EAF1 B_S L2 # Продължи със следващия символ от низа 21 0032 08B9 L5: ASL_S r1,r1,8 # Измести текущия адрес в r1:r2 с 1 байт наляво 22 0034 412A 0406 LSR r4,r2,24 23 0038 0521 0101 OR r1,r1,r4 24 003c 08BA ASL_S r2,r2,8 25 003e 657A OR_S r2,r2,r3# Запиши текущия байт отдясно 26 0040 E1EC BRNE_S r12,0,L1# Разделител, а не терминатор - получи следващия байт 27 0042 4040 MOV_S r0,r2 # Терминатор – върни адреса в r1:r0 28 0044 E07E J_S [blink] PPC GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри r3:r4 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър r3. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 3863FFFF addi r3,r3,-1# Компенсирай преинкрементната адресация 8 0004 38800000 li r4,0 # Започни начисто 9 0008 38C00000 L1: li r6,0 # Нов текущ байт - започни натрупването от нулата 10 000c 8CE30001 L2: lbzu r7,1(r3)# Зареди поредния символ 11 0010 28070030 cmplwi r7,'0 # Цифра? 12 0014 41800038 blt L5 # Не, разделител или терминатор е - байтът е готов 13 0018 28070039 cmplwi r7,'9 14 001c 4181000C bgt L3 # Не, провери за буква или разделител 15 0020 38E7FFD0 addi r7,r7,-'0#Да, преобразувай от ASCII-код в тетрада битове 16 0024 4800001C b L4 17 0028 70E700DF L3: andi. r7,r7,~('a-'A) & 0xFF# Преобразувай евентуална малка буква 18 002c 28070041 cmplwi r7,'A # в главна; главна буква? 19 0030 4180001C blt L5 # Не, разделител е - байтът е готов 20 0034 28070046 cmplwi r7,'F 21 0038 41810014 bgt L5 # Не, също 22 003c 38E7FFC9 addi r7,r7,10-'A# Да, преобразувай от ASCII-код в тетрада битове 23 0040 54C62036 L4: slwi r6,r6,4 # Направи място за новата шестнадесетична цифра 24 0044 7CC63A14 add r6,r6,r7# и я добави към текущата стойност 25 0048 4BFFFFC4 b L2 # Продължи със следващия символ от низа 26 004c 54A5402E L5: slwi r5,r5,8 # Измести текущия адрес в r5:r4 с 1 байт наляво 27 0050 5085463E rlwimi r5,r4,8,24,31 28 0054 5484402E slwi r4,r4,8 29 0058 7C843378 or r4,r4,r6# Запиши текущия байт отдясно 30 005c 28070000 cmplwi r7,0 # Край на низа? 31 0060 4082FFA8 bne L1 # Не, продължи със следващия байт 32 0064 7CA32B78 mr r3,r5 # Да, върни адреса в r3:r4 33 0068 4E800020 blr SPARC GAS getmacst.s page 1 1 ! Да се напише подпрограма, която да връща в регистри %o0:%o1 MAC-адреса, 2 ! получен от низа тип ASCIIZ с начален адрес в регистър %o0. Низът е в 16-ичен 3 ! вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 92100000 clr %o1 ! Започни начисто 8 0004 96100000 L1: clr %o3 ! Нов текущ байт - започни натрупването от нулата 9 0008 D80A0000 L2: ldub [%o0],%o4! Зареди поредния символ 10 000c 90022001 add %o0,1,%o0! Обнови адреса 11 0010 80A32030 cmp %o4,'0' ! Цифра? 12 0014 0A800010 bcs L5 ! Не, разделител или тарминатор е - байтът е готов 13 0018 80A32039 cmp %o4,'9' 14 001c 18800004 bgu L3 ! Не, провери за буква или разделител 15 0020 01000000 nop 16 0024 10800009 ba L4 ! (изпълнява се след „sub“) 17 0028 98232030 sub %o4,'0',%o4! Да, преобразувай от ASCII-код в тетрада битове 18 002c 980B20DF L3: and %o4,~('a'-'A') & 0xFF,%o4! Преобразувай евентуална малка буква 19 0030 80A32041 cmp %o4,'A' ! в главна; главна буква? 20 0034 0A800008 bcs L5 ! Не, разделител е - байтът е готов 21 0038 80A32046 cmp %o4,'F' 22 003c 18800006 bgu L5 ! Не, също 23 0040 01000000 nop 24 0044 98232037 sub %o4,'A'-10,%o4! Да, преобразувай от ASCII-код в тетрада битове 25 0048 972AE004 L4: sll %o3,4,%o3! Направи място за новата шестнадесетична цифра 26 004c 10BFFFEF ba L2 !(продължи със следващия символ; изпълнява се след add) 27 0050 9602C00C add %o3,%o4,%o3! Добави я към текущата стойност 28 0054 952AA008 L5: sll %o2,8,%o2! Измести текущия адрес в %o2:%o1 с 1 байт наляво 29 0058 9B326018 srl %o1,24,%o5 30 005c 9412800D or %o2,%o5,%o2 31 0060 932A6008 sll %o1,8,%o1 32 0064 80A32000 cmp %o4,0 ! Последен байт? 33 0068 12BFFFE7 bne L1 ! Не, продължи със следващия; изпълнява се след „or“ 34 006c 9212400B or %o1,%o3,%o1! (Запиши текущия байт отдясно) 35 0070 81C3E008 retl 36 0074 9010000A mov %o2,%o0 ! Да, върни адреса в %o0:%o1; изпълнява се преди „retl“ MIPS GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри $2:$3 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър $4. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .ent getmacst 6 .global getmacst 7 getmacst: 8 0000 24030000 LI $3,0 # Започни начисто 9 0004 24060000 L1: LI $6,0 # Нов текущ байт - започни натрупването от нулата 10 0008 90880000 L2: LBU $8,0($4) # Зареди поредния символ 11 000c 24840001 ADDIU $4,$4,1 # Обнови адреса 12 0010 2D090030 SLTIU $9,$8,'0' # Цифра? 13 0014 15200011 00000000 BNE $9,$0,L5 # Не, разделител или терминатор е - байтът е готов 14 001c 2D09003A SLTIU $9,$8,'9'+1 15 0020 11200003 00000000 BEQ $9,$0,L3 # Не, провери за буква или разделител 16 ADDIU $8,$8,-'0' # Да, преобразувай от ASCII-код в тетрада битове 17 0028 10000009 2508FFD0 B L4 18 0030 310800DF L3: ANDI $8,$8,~('a'-'A') & 0xFF # Преобразувай евентуална малка буква 19 0034 2D090041 SLTIU $9,$8,'A' # в главна; главна буква? 20 0038 15200008 00000000 BNE $9,$0,L5 # Не, разделител е - байтът е готов 21 0040 2D090047 SLTIU $9,$8,'F'+1 22 0044 11200005 00000000 BEQ $9,$0,L5 # Не, също 23 004c 2508FFC9 ADDIU $8,$8,10-'A'# Да, преобразувай от ASCII-код в тетрада битове 24 0050 00063100 L4: SLL $6,$6,4 # Направи място за новата шестнадесетична цифра 25 ADDU $6,$6,$8 # и я добави към текущата стойност 26 0054 1000FFEC 00C83021 B L2 # Продължи със следващия символ от низа 27 005c 00021200 L5: SLL $2,$2,8 # Измести текущия адрес в $2:$3 с 1 байт наляво 28 0060 00231E02 ROTR $3,$3,24 29 0064 7C623804 INS $2,$3,0,8 30 INS $3,$6,0,8 # Запиши текущия байт отдясно 31 0068 1500FFE6 7CC33804 BNE $8,$0,L1 # Ако има още байтове, продължи със следващия байт 32 0070 03E00008 00000000 JR $31 # Ако не, върни адреса в $2:$3 33 0078 00000000 00000000 .end getmacst RISC-V GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри a1:a0 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър a0. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 8146 LI a3,0 # Започни начисто 8 0002 0146 L1: LI a2,0 # Нов текущ байт - започни натрупването от нулата 9 0004 03470500 L2: LBU a4,0(a0) # Зареди поредния символ 10 0008 0505 ADDI a0,a0,1 # Обнови адреса 11 000a 93370703 SLTIU a5,a4,'0' # Цифра? 12 000e 85E7 BNEZ a5,L5 # Не, разделител или терминатор е - байтът е готов 13 0010 9337A703 SLTIU a5,a4,'9'+1 14 0014 81C7 BEQZ a5,L3 # Не, провери за буква или разделител 15 0016 130707FD ADDI a4,a4,-'0' # Да, преобразувай от ASCII-код в тетрада битове 16 001a 19A8 J L4 17 001c 1377F70D L3: ANDI a4,a4,~('a'-'A') & 0xFF # Преобразувай евентуална малка буква 18 0020 93371704 SLTIU a5,a4,'A' # в главна; главна буква? 19 0024 89EB BNEZ a5,L5 # Не, разделител е - байтът е готов 20 0026 93377704 SLTIU a5,a4,'F'+1 21 002a 91C7 BEQZ a5,L5 # Не, също 22 002c 130797FC ADDI a4,a4,10-'A'# Да, преобразувай от ASCII-код в тетрада битове 23 0030 1206 L4: SLLI a2,a2,4 # Направи място за новата шестнадесетична цифра 24 0032 3A96 ADD a2,a2,a4 # и я добави към текущата стойност 25 0034 C1BF J L2 # Продължи със следващия символ от низа 26 0036 A205 L5: SLLI a1,a1,8 # Измести текущия адрес в a1:a3 с 1 байт наляво 27 0038 13D88601 SRLI a6,a3,24 28 003c B3E50501 OR a1,a1,a6 29 0040 A206 SLLI a3,a3,8 30 0042 D18E OR a3,a3,a2 # Запиши текущия байт отдясно 31 0044 5DFF BNEZ a4,L1 # Ако има още байтове, продължи със следващия байт 32 0046 3685 MV a0,a3 # Ако не, върни адреса в r1:r0 33 0048 8280 RET Nios II GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри r3:r2 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър r4. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 14008000 MOVUI r2,0 # Започни начисто 8 0004 14008001 L1: MOVUI r6,0 # Нов текущ байт - започни натрупването от нулата 9 0008 03000022 L2: LDBU r8,(r4) # Зареди поредния символ 10 000c 44000021 ADDI r4,r4,1 # Обнови адреса 11 0010 300C4042 CMPLTUI r9,r8,'0' # Цифра? 12 0014 1E0D0048 BNE r9,r0,L5 # Не, разделител или терминатор е - байтът е готов 13 0018 B00E4042 CMPLTUI r9,r8,'9'+1 14 001c 26020048 BEQ r9,r0,L3 # Не, провери за буква или разделител 15 0020 04F43F42 SUBI r8,r8,'0' # Да, преобразувай от ASCII-код в тетрада битове 16 0024 06060000 BR L4 17 0028 CC370042 L3: ANDI r8,r8,~('a'-'A') & 0xFF # Преобразувай евентуална малка буква 18 002c 70104042 CMPLTUI r9,r8,'A' # в главна; главна буква? 19 0030 1E060048 BNE r9,r0,L5 # Не, разделител е - байтът е готов 20 0034 F0114042 CMPLTUI r9,r8,'F'+1 21 0038 26040048 BEQ r9,r0,L5 # Не, също 22 003c 44F23F42 SUBI r8,r8,'A'-10# Да, преобразувай от ASCII-код в тетрада битове 23 0040 3A910C30 L4: SLLI r6,r6,4 # Направи място за новата шестнадесетична цифра 24 0044 3A880D32 ADD r6,r6,r8 # и я добави към текущата стойност 25 0048 06EF3F00 BR L2 # Продължи със следващия символ от низа 26 004c 3A920618 L5: SLLI r3,r3,8 # Измести текущия адрес в r3:r2 с 1 байт наляво 27 0050 3AD61410 SRLI r10,r2,24 28 0054 3AB0861A OR r3,r3,r10 29 0058 3A920410 SLLI r2,r2,8 30 005c 3AB08411 OR r2,r2,r6 # Запиши текущия байт отдясно 31 0060 1EE83F40 BNE r8,r0,L1 # Ако има още байтове, продължи със следващия байт 32 0064 3A2800F8 RET # Ако не, върни адреса в r3:r2 Xtensa GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри a3:a2 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър a2. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 0C05 MOVI a5,0 # Започни начисто 8 0002 0C04 L1: MOVI a4,0 # Нов текущ байт - започни натрупването от нулата 9 0004 620200 L2: L8UI a6,a2,0 # Зареди поредния символ 10 0007 1B22 ADDI a2,a2,1 # Обнови адреса 11 0009 3C07 MOVI a7,'0' # Цифра? 12 000b 773625 BLTU a6,a7,L5 # Не, разделител или терминатор е - байтът е готов 13 000e 3CA7 MOVI a7,'9'+1 14 0010 77B605 BGEU a6,a7,L3 # Не, провери за буква или разделител 15 0013 62C6D0 ADDI a6,a6,-'0' # Да, преобразувай от ASCII-код в тетрада битове 16 0016 860400 J L4 17 0019 72A0DF L3: MOVI a7,~('a'-'A') & 0xFF 18 001c 706610 AND a6,a6,a7 # Преобразувай евентуална малка буква 19 001f 4C17 MOVI a7,'A' # в главна; главна буква? 20 0021 77360F BLTU a6,a7,L5 # Не, разделител е - байтът е готов 21 0024 4C77 MOVI a7,'F'+1 22 0026 77B60A BGEU a6,a7,L5 # Не, също 23 0029 62C6C9 ADDI a6,a6,10-'A'# Да, преобразувай от ASCII-код в тетрада битове 24 002c C04411 L4: SLLI a4,a4,4 # Направи място за новата шестнадесетична цифра 25 002f 6A44 ADD a4,a4,a6 # и я добави към текущата стойност 26 0031 C6F3FF J L2 # Продължи със следващия символ от низа 27 0034 803311 L5: SLLI a3,a3,8 # Измести текущия адрес в a3:a5 с 1 байт наляво 28 0037 508875 EXTUI a8,a5,24,8 29 003a 803320 OR a3,a3,a8 30 003d 805511 SLLI a5,a5,8 31 0040 405520 OR a5,a5,a4 # Запиши текущия байт отдясно 32 0043 56B6FB BNEZ a6,L1 # Ако има още байтове, продължи със следващия байт 33 0046 2D05 MOV a2,a5 # Ако не, върни адреса в a3:a2 34 0048 0DF0 RET 88K GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри r2:r3 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър r2. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global _getmacst 6 0000 F4605800 _getmacst: 7 0004 F4A05800 or r3,r0,r0 # Започни начисто 8 0008 F4C20C00 L1: or r5,r0,r0 # Нов текущ байт - започни натрупването от нулата 9 000c 60420001 L2: ld.bu r6,r2,r0 # Зареди поредния символ 10 0010 7CE60030 addu r2,r2,1 # Обнови адреса 11 0014 D947000E cmp r7,r6,'0' # Цифра? 12 0018 7CE60039 bb1 lo,r7,L5 # Не, разделител или терминатор е - байтът е готов 13 001c D9070003 cmp r7,r6,'9' 14 0020 64C60030 bb1 hi,r7,L3 # Не, провери за буква или разделител 15 0024 C0000007 subu r6,r6,'0' # Да, преобразувай от ASCII-код в тетрада битове 16 0028 48C600DF br L4 17 002c 7CE60041 L3: mask r6,r6,~('a-'A) & 0xFF# Преобразувай евентуална малка буква 18 0030 D9470007 cmp r7,r6,'A' # в главна; главна буква? 19 0034 7CE60046 bb1 lo,r7,L5 # Не, разделител е - байтът е готов 20 0038 D9070005 cmp r7,r6,'F' 21 003c 64C60037 bb1 hi,r7,L5 # Не, също 22 0040 F0A5A004 subu r6,r6,'A'-10# Да, преобразувай от ASCII-код в тетрада битове 23 0044 F4A56006 L4: mak r5,r5,0<4> # Направи място за новата шестнадесетична цифра 24 0048 C3FFFFF0 addu r5,r5,r6 # и я добави към текущата стойност 25 004c F084A008 br L2 # Продължи със следващия символ от низа 26 0050 F0E39918 L5: mak r4,r4,0<8> # Измести текущия адрес в r4:r3 с 1 байт наляво 27 0054 F4875804 extu r7,r3,8<24> 28 0058 F063A008 or r4,r7,r4 29 005c F4635805 mak r3,r3,0<8> 30 0060 E9A6FFE9 or r3,r3,r5 # Запиши текущия байт отдясно. Край на низа? 31 0064 F4445800 bcnd ne0,r6,L1 # Не, продължи със следващия байт 32 0068 F400C001 or r2,r4,r0 # Да, върни адреса в r2:r3 jmp r1 Or1k GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри R11:R12 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър R3. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 E1800004 L.OR R12,R0,R0 # Започни начисто 8 0004 E0C00004 L1: L.OR R6,R0,R0# Нов текущ байт - започни натрупването от нулата 9 0008 8CA30000 L2: L.LBZ R5,0(R3)# Зареди поредния символ 10 000c 9C630001 L.ADDI R3,R3,1 # Обнови адреса 11 0010 BC650030 L.SFGEUI R5,'0' # Цифра? 12 0014 0C000010 L.BNF L5 # Не, разделител или тарминатор е - байтът е готов 13 0018 BCA50039 L.SFLEUI R5,'9' 14 001c 0C000004 L.BNF L3 # Не, провери за буква или разделител 15 0020 15000000 L.NOP 0 16 0024 00000009 L.J L4 # (изпълнява се след „L.ADDI“!) 17 0028 9CA5FFD0 L.ADDI R5,R5,-'0' # Да, преобразувай от ASCII-код в тетрада битове 18 002c A4A500DF L3: L.ANDI R5,R5,~('a'-'A') & 0xFF # Преобразувай евентуална малка буква 19 0030 BC650041 L.SFGEUI R5,'A' # в главна; главна буква? 20 0034 0C000008 L.BNF L5 # Не, разделител е - байтът е готов 21 0038 BCA50046 L.SFLEUI R5,'F' 22 003c 0C000006 L.BNF L5 # Не, също 23 0040 15000000 L.NOP 0 24 0044 9CA5FFC9 L.ADDI R5,R5,10-'A' # Да, преобразувай от ASCII-код в тетрада битове 25 0048 B8C60004 L4: L.SLLI R6,R6,4 # Направи място за новата шестнадесетична цифра 26 004c 03FFFFEF L.J L2 # (продължи със следващия символ; изп.се след „L.ADD“!) 27 0050 E0C62800 L.ADD R6,R6,R5# Добави я към текущата стойност 28 0054 B96B0008 L5: L.SLLI R11,R11,8 # Измести текущия адрес в R11:R12 с 1 байт наляво 29 0058 B88C0058 L.SRLI R4,R12,24 30 005c E16B2004 L.OR R11,R11,R4 31 0060 B98C0008 L.SLLI R12,R12,8 32 0064 E4050000 L.SFEQ R5,R0 # Последен байт? 33 0068 0FFFFFE7 L.BNF L1 # Не, продължи със следващия; изпълнява се след „L.OR“! 34 006c E18C3004 L.OR R12,R12,R6 # (Запиши текущия байт отдясно) 35 0070 44004800 L.JR LR # Да, върни адреса в R11:R12 36 0074 15000000 L.NOP 0 Xilinx MicroBlaze GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри R4:R3 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър R5. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 00006080 OR R3,R0,R0# Започни начисто 8 0004 0000C080 L1: OR R6,R0,R0# Нов текущ байт - започни натрупването от нулата 9 0008 0000E5E0 L2: LBUI R7,R5,0 # Зареди поредния символ 10 000c 0100A520 ADDI R5,R5,1 # Обнови адреса 11 0010 D0FF0721 ADDI R8,R7,-'0'# Цифра? 12 0014 380048BC BLTI R8,L5 # Не, разделител или терминатор е - байтът е готов 13 0018 C7FF0721 ADDI R8,R7,-'9' 14 001c 0C0088BC BGTI R8,L3 # Не, провери за буква или разделител 15 0020 D0FFE720 ADDI R7,R7,-'0'#Да, преобразувай от ASCII-код в тетрада битове 16 0024 1C0000B8 BRI L4 17 0028 DF00E7A4 L3: ANDI R7,R7,~('a'-'A') & 0xFF# Преобразувай евентуална малка буква 18 002c BFFF0721 ADDI R8,R7,-'A'# в главна; главна буква? 19 0030 1C0048BC BLTI R8,L5 # Не, разделител е - байтът е готов 20 0034 BAFF0721 ADDI R8,R7,-'F' 21 0038 140088BC BGTI R8,L5 # Не, също 22 003c C9FFE720 ADDI R7,R7,10-'A'# Да, преобразувай от ASCII-код в тетрада битове 23 0040 0404C664 L4: BSLLI R6,R6,4 # Направи място за новата шестнадесетична цифра 24 0044 0038C600 ADD R6,R6,R7# и я добави към текущата стойност 25 0048 C0FF00B8 BRI L2 # Продължи със следващия символ от низа 26 004c 08048464 L5: BSLLI R4,R4,8 # Измести текущия адрес в R4:R3 с 1 байт наляво 27 0050 18000365 BSRLI R8,R3,24 28 0054 00408480 OR R4,R4,R8 29 0058 08046364 BSLLI R3,R3,8 30 005c 00306380 OR R3,R3,R6# Запиши текущия байт отдясно 31 0060 A4FF27BC BNEI R7,L1 # Ако не е терминатор, продължи със следващия байт 32 0064 08000FB6 RTSD R15,8 # Върни адреса в R4:R3 33 0068 00000080 NOP HPPA GAS getmacst.s page 1 1 ; Да се напише подпрограма, която да връща в регистри %R28:%R29 MAC-адреса, 2 ; получен от низа тип ASCIIZ с начален адрес в регистър %R26. Низът е в 16-ичен 3 ; вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .text 6 .global getmacst 7 getmacst: 8 0000 341C0000 LDI 0,%R28 9 0004 341D0000 LDI 0,%R29 ; Започни начисто 10 0008 34170000 L1: LDI 0,%R23 ; Нов текущ байт - започни натрупването от нулата 11 000c 0F421039 L2: LDBS,MA 1(%R26),%R25 ; Зареди поредния символ 12 0010 9320A060 COMICLR,<<= '0,%R25,%R0; Разделител или терминатор? 13 0014 E800005A B,N L4 ; Да, байтът е готов 14 0018 93204072 COMICLR,< '9,%R25,%R0; Не, цифра? 15 001c E800002A B,N L3 ; Да, преобразувай я от ASCII 16 0020 D7201CBF DEPI 0,26,1,%R25 ; Не, преобразувай евентуална малка буква в главна 17 0024 9320A082 COMICLR,<<= 'A,%R25,%R0 ; Разделител? 18 0028 E8000032 B,N L4 ; Да, байтът е готов 19 002c 9320908C COMICLR,>>= 'F,%R25,%R0 ; Буква? 20 0030 E8000022 B,N L4 ; Не, разделител – байтът е готов 21 0034 B73907F3 ADDI 10-'A+'0,%R25,%R25; Да, реобразувай буквата от ASCII в 2 стъпки 22 0038 B73907A1 L3: ADDI -'0,%R25,%R25; Цифра – преобразувай от ASCII в двоичнодесетичен 23 003c 08170A97 SH2ADDL %R23,%R0,%R23; Добави тетрадата към изместения с 4 б.текущ байт 24 0040 E81F1F8D B L2 ; Продължи със следващия символ от низа 25 0044 0B370A97 SH2ADDL %R23,%R25,%R23; (изпълнява се преди „B“!) 26 0048 D79C0D08 L4: DEP %R28,23,24,%R28 27 004c D3BD08FD SHD %R29,%R29,24,%R29 28 0050 D79D0C18 DEP %R29,31,8,%R28; Измести текущия адрес в %R28:%R29 с байт наляво 29 0054 8F203F5D COMIBF,= 0,%R25,L1 ; Ако последният символ не е терминатор, продължи 30 0058 D7B70C18 DEP %R23,31,8,%R29; Запиши текущия байт отдясно (изп.се преди COMBF 31 005c E840C002 BV,N (%R2) ; Върни MAC-адреса в %R28:%R29 Renesas / SuperH SH GAS Little Endian getmacst.s page 1 1 ! Да се напише подпрограма, която да връща в регистри R1:R0 MAC-адреса, 2 ! получен от низа тип ASCIIZ с начален адрес в регистър R4. Низът е в 16-ичен 3 ! вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 00E0 MOV #0,R0 ! Започни начисто 8 0002 00E3 L1: MOV #0,R3 ! Нов текущ байт - започни натрупването от нулата 9 0004 4462 L2: MOV.B @R4+,R2 ! Зареди поредния символ и обнови адреса 10 0006 30E5 MOV #'0',R5 11 0008 5232 CMP/HS R5,R2 ! Цифра? 12 000a 118B BF L5 ! Не, разделител или тарминатор е - байтът е готов 13 000c 39E5 MOV #'9',R5 14 000e 5632 CMP/HI R5,R2 15 0010 0189 BT L3 ! Не, провери за буква или разделител 16 0012 D072 ADD #-'0',R2! Да, преобразувай от ASCII-код в тетрада битове 17 0014 088B BF L4 18 0016 DFE5 L3: MOV #~('a'-'A'),R5 19 0018 5922 AND R5,R2 ! Преобразувай евентуална малка буква в главна 20 001a 41E5 MOV #'A',R5 21 001c 5232 CMP/HS R5,R2 ! Главна буква? 22 001e 078B BF L5 ! Не, разделител е - байтът е готов 23 0020 46E5 MOV #'F',R5 24 0022 5632 CMP/HI R5,R2 25 0024 0489 BT L5 ! Не, също 26 0026 C972 ADD #10-'A',R2! Да, преобразувай от ASCII-код в тетрада битове 27 0028 0843 L4: SHLL2 R3 ! Направи място за новата шестнадесетична цифра 28 002a 0843 SHLL2 R3 29 002c 2C33 ADD R2,R3 ! Добави я към текущата стойност 30 002e E98B BF L2 ! Продължи със следващия символ (T = 0) 31 0030 1841 L5: SHLL8 R1 ! Измести текущия адрес в R1:R0 с 1 байт наляво 32 0032 0365 MOV R0,R5 33 0034 2945 SHLR16 R5 34 0036 1945 SHLR8 R5 35 0038 5B21 OR R5,R1 36 003a 1840 SHLL8 R0 37 003c 3B20 OR R3,R0 ! Запиши текущия байт отдясно 38 003e 1542 CMP/PL R2 ! Последен байт? 39 0040 DF89 BT L1 ! Не, продължи със следващия 40 0042 0B00 RTS ! Да, върни адреса в R1:R0 41 0044 0900 NOP GAS for CRIS getmacst.s page 1 1 ; Да се напише подпрограма, която да връща в регистри R11:R10 MAC-адреса, 2 ; получен от низа тип ASCIIZ с начален адрес в регистър R10. Низът е в 16-ичен 3 ; вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 0000 7C86 CLEAR.D $R12 ; Започни начисто 8 0002 7D86 L1: CLEAR.D $R13 ; Нов текущ байт - започни натрупването от нулата 9 0004 4A9C L2: MOVU.B [$R10+],$R9; Зареди поредния символ и обнови адреса 10 0006 CF9E3000 CMP.B '0',$R9 ; Цифра? 11 000a 2810 BLO L5 ; Не, разделител или тарминатор е - байтът е готов 12 000c CF9E3900 CMP.B '9',$R9 13 0010 0890 BHI L3 ; Не, провери за буква или разделител 14 0012 B005 NOP 15 0014 18E0 BA L4 ; (изпълнява се след „SUBQ“) 16 0016 B092 SUBQ '0',$R9 ; Да, преобразувай от ASCII-код в тетрада битове 17 0018 0F9FDFFF L3: AND.B ~('a'-'A'),$R9; Преобразувай евентуална малка буква 18 001c CF9E4100 CMP.B 'A',$R9 ; в главна; главна буква? 19 0020 1210 BLO L5 ; Не, разделител е - байтът е готов 20 0022 CF9E4600 CMP.B 'F',$R9 21 0026 0C90 BHI L5 ; Не, също 22 0028 B005 NOP 23 002a B792 SUBQ 'A'-10,$R9; Да, преобразувай от ASCII-код в тетрада битове 24 002c C4D3 L4: LSLQ 4,$R13 ; Направи място за новата шестнадесетична цифра 25 002e D7E0 BA L2 ;(продължи със следващия символ; изпълнява се след ADD) 26 0030 09D6 ADD.B $R9,$R13; Добави я към текущата стойност 27 0032 C8B3 L5: LSLQ 8,$R11 ; Измести текущия адрес в R11:R12 с 1 байт наляво 28 0034 6CF6 MOVE.D $R12,$R15 29 0036 F8F3 LSRQ 24,$R15 30 0038 4FB7 OR.B $R15,$R11 31 003a C8C3 LSLQ 8,$R12 32 003c C092 CMPQ 0,$R9 ; Последен байт? 33 003e C520 BNE L1 ; Не, продължи със следващия; изпълнява се след „OR“ 34 0040 4DC7 OR.B $R13,$R12; (Запиши текущия байт отдясно) 35 0042 F0B9 RET 36 0044 6CA60000 MOVE.D $R12,$R10; Да, върни адреса в R11:R10; изпълнява се преди „RET“ BFIN GAS getmacst.s page 1 1 # Да се напише подпрограма, която да връща в регистри R1:R0 MAC-адреса, 2 # получен от низа тип ASCIIZ с начален адрес в регистър R0. Низът е в 16-ичен 3 # вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global _getmacst 6 _getmacst: 7 0000 E305 [--SP] = (R7:4, P5:3);# Съхрани R4–R7/P3–P5 (82-000410-03, стр. 1-433) 8 0002 0032 P0 = R0; # Адресът на низа трябва да бъде в адресен регистър 9 0004 0058 R0 = R0 ^ R0; # Започни начисто 10 0006 9258 L_1: R2 = R2 ^ R2; # Нов текущ байт - започни натрупването от нулата 11 0008 0498 L_2: R4 = B [P0++] (Z); # Зареди поредния символ и обнови адреса 12 000a 8361 R3 = '0' (X); 13 000c 9C09 CC = R4 < R3 (IU); # Цифра? 14 000e 1318 IF CC JUMP L_5; # Не, разделител или терминатор е - байтът е готов 15 0010 CB61 R3 = '9' (X); 16 0012 A309 CC = R3 < R4 (IU); 17 0014 0318 IF CC JUMP L_3; # Не, провери за буква или разделител 18 0016 8466 R4 += -'0'; # Да, преобразувай от ASCII-код в тетрада битове 19 0018 0B20 JUMP L_4; 20 001a 2C4C L_3: BITCLR (R4, 5); # Преобразувай евентуална малка буква в главна 21 001c 23E14100 R3 = 'A' (X); 22 0020 9C09 CC = R4 < R3 (IU); # Главна буква? 23 0022 0918 IF CC JUMP L_5; # Не, разделител е - байтът е готов 24 0024 23E14600 R3 = 'F' (X); 25 0028 A309 CC = R3 < R4 (IU); 26 002a 0518 IF CC JUMP L_5; # Не, също 27 002c 4C66 R4 += 10-'A'; # Да, преобразувай от ASCII-код в тетрада битове 28 002e 224F L_4: R2 <<= 4; # Направи място за новата шестнадесетична цифра 29 0030 A250 R2 = R2 + R4; # и я добави към текущата стойност 30 0032 EB2F JUMP L_2; # Продължи със следващия символ от низа 31 0034 414F L_5: R1 <<= 8; # Измести текущия адрес в R1:R0 с 1 байт наляво 32 0036 82C64087 R3 = R0 >> 24; 33 003a 5956 R1 = R1 | R3; 34 003c 404F R0 <<= 8; 35 003e 1056 R0 = R0 | R2; # Запиши текущия байт отдясно 36 0040 040C CC = R4 == 0; # Има ли още байтове (нулев терминатор)? 37 0042 E213 IF !CC JUMP L_1; # Да, продължи със следващия байт 38 0044 A305 (R7:4, P5:3) = [SP++];# Не, възстанови сърнанените регистри 39 0046 1000 RTS; # и върни адреса в R1:R0 Hexagon GAS getmacst.s page 1 1 // Да се напише подпрограма, която да връща в регистри R1:R0 MAC-адреса, 2 // получен от низа тип ASCIIZ с начален адрес в регистър R0. Низът е в 16-ичен 3 // вид с разделител между байтовете препинателен знак, напр. 00-0C-76-1F-C5-EB 4 5 .global getmacst 6 getmacst: 7 { R2 = R0 // Освободи R0 за операции с двойна дума 8 0000 003C0230 R1:0 = #0 } // Започни начисто 9 0004 03C00078 L1: R3 = #0 // Нов текущ байт - започни натрупването от нулата 10 0008 24C0229B L2: R4 = MEMUB(R2++#1) // Зареди поредния символ и обнови адреса 11 { P0 = CMP.GEU(R4,#'0') // Цифра? 12 000c E0458475 18C8205C IF (!P0.NEW) JUMP:NT L4 }// Не, разделител или терминатор е 13 { P0 = !CMP.GTU(R4,#'9') 14 IF (P0.NEW) R4 = ADD(R4,#-'0') // Да, преобразувай от ASCII в тетрада 15 0014 30478475 0E58005C 04FA0474 IF (P0.NEW) JUMP:T L3 } 16 0020 24C5C48C R4 = CLRBIT(R4,#5) // Преобразувай евентуална малка буква в главна 17 { P0 = CMP.GEU(R4,#'A') 18 P0 = !CMP.GTU(R4,#'F') //Главна буква? 19 0024 00488475 D0488475 24F90474 IF (P0.NEW) R4 = ADD(R4,#10-'A') }//Да, преобразувай от ASCII в тетрада 20 0030 45C4038C L3: R5 = ASL(R3,#4) // Добави я към умножената по 16 текуща стойност 21 { IF (P0) R3 = ADD(R5,R4)// (уви, няма условна команда „ADDASL“!) 22 0034 034405FB EAE0DF5C IF (P0) JUMP L2 } // и продължи със следващия символ от низа 23 003c 40C80080 L4: R1:0 = ASL(R1:0,#8) // Измести текущия адрес в R1:R0 с 1 байт наляво 24 { R0 = OR(R0,R3) // Запиши текущия байт отдясно 25 0040 E27F2461 00C320F1 IF (R4!=#0) JUMP:T L1 }//Не е край на низа? Продължи със следващия байт 26 0048 00C09F52 JUMPR LR // Да, върни адреса в R1:R0 S/390 GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър 4, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри 2:3. 4 5 .global putmacst 6 putmacst: 7 0000 A758000C LHI 5,12 # Инициализирай брояча на тетрадите 8 0004 1802 L1: LR 0,2 # Зареди нова тетрада (от старша към младша) 9 0006 8800000C SRL 0,12 10 000a A718000F LHI 1,0xF 11 000e 1401 NR 0,1 # Изолирай я 12 0010 89200004 SLL 2,4 # Измести MAC-адреса с 1 тетрада наляво, 13 0014 1813 LR 1,3 # запълвайки освободената междинна тетрада: 14 0016 8810001C SRL 1,28 # Направи най-старшата тетрада най-младша 15 001a 1621 OR 2,1 # Копирай я на освободеното място 16 001c 89300004 SLL 3,4 # Измести младшата дума 17 0020 A70E000A CHI 0,0xA # Буква от A до F? 18 0024 A7440004 JL L2 # Не, цифра е - само добави ASCII-кода на 0 19 0028 A70A0007 AHI 0,'A'-0xA-'0' # Да, превърни с отчитане добавянето на '0' 20 002c A70A0030 L2: AHI 0,'0' # Превърни (завърши преобразуването) в ASCII 21 0030 42004000 STC 0,0(4) # Запиши така получения ASCII-код в низа 22 0034 A74A0001 AHI 4,1 # Обнови адреса 23 0038 A7510001 TML 5,1 # Четна тетрада (нечетна стойност на брояча)? 24 003c A7840006 JZ L3 # Не, продължи с младшата цифра на този байт 25 0040 922D4000 MVI 0(4),'-' # Да, запиши разделителя в низа 26 0044 A74A0001 AHI 4,1 # Обнови адреса 27 0048 A756FFDE L3: BRCT 5,L1 # Премини към обработка на следващата тетрада 28 004c A74AFFFF AHI 4,-1 # Замени шестото излишно тире с терминатор 0, 29 0050 42504000 STC 5,0(4) # връщайки се с 1 назад към неговия адрес 30 0054 07FE0707 BR 14 ==> id32/putmacst.s <== 1 * Write at an address passed in 7(8) -> reg. 4 an ASCIIZ string in hexadecimal 2 * format with a hyphen as a byte delimiter, obtained from a 48-bit MAC-address 3 * passed in 7(0):7(4) -> registers 2:3. 4 5 entry putmacst 00000000d 6 putmacst equ * 00000d 5827 0000 7 l 2,0(7) MAC-address (high word) 00004d 5837 0004 8 l 3,4(7) " " " (low word) 00008d 5847 0008 9 l 4,8(7) String buffer address 0000Cd 245C 10 lis 5,12 Initialise the nibble counter 0000Ed 0802 11 L1 lr 0,2 Load a new nibble (from high to low) 00010d 100C 12 srls 0,12 Place it on the lowmost 4 bits 00012d C400 000F 13 nhi 0,x'f'(0) Mask it 00016d 1124 14 slls 2,4 Shift the MAC address left by 1 nibble, 00018d 0813 15 lr 1,3 filling in the released intermediate nibble: 0001Ad EC10 001C 16 srl 1,28(0) Make the highmost nibble lowmost 0001Ed 0621 17 or 2,1 Copy it to the freed place 00020d 1134 18 slls 3,4 Shift the low word 00022d C500 000A 19 clhi 0,x'a'(0) A letter from A to F? 00026d 2182 0000002Ad 20 bls L2 No, it's a digit - just add ASCII '0' 00028d 2607 21 ais 0,c'A'-x'a'-c'0' Yes, convert considering next adding of '0' 0002Ad CA00 0030 22 L2 ahi 0,c'0'(0) Convert (finish conversion) to ASCII 0002Ed D204 0000 23 stb 0,0(4) Write the so obtained ASCII-code to the string 00032d 2641 24 ais 4,1 Update the address 00034d C350 0001 25 thi 5,1(0) An even nibble (odd counter value)? 00038d 2336 00000044d 26 bzs L3 No, continue with the low digit of this byte 0003Ad C800 002D 27 lhi 0,c'-'(0) Yes, write a delimiter to the string 0003Ed D204 0000 28 stb 0,0(4) 00042d 2641 29 ais 4,1 Update the address 00044d 2751 30 L3 sis 5,1 Last nibble? 00046d 4230 FFC4 0000000Ed 31 bnz L1(0) No, go process the next one 0004Ad D254 40FF FFFF 32 stb 5,-1(4) Yes, replace the sixth excessive hyphen with 0 00050d 030F 33 br 15 Return to the calling function VAX GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в AP(12) -> R2, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в AP(4) -> R1:R0. 4 5 .global _putmacst 6 _putmacst: 7 0000 1C00 .word 0x1C # R2-R4 (R3 = брояч на тетрадите, R4 = тетрада) 8 0002 FD7DAC04 50 MOVO 4(AP),R0 # R1:R0 = MAC-адрес, R2 = начален адрес на низа 9 0007 D00C53 MOVL $12,R3 # Инициализирай брояча на тетрадите 10 000a EF0C0451 54 L1: EXTZV $12,$4,R1,R4 # Зареди нова тетрада (от старша към младша) 11 000f 79045050 ASHQ $4,R0,R0 # Измести MAC-адреса с 1 тетрада наляво 12 0013 3D393054 0300 ACBW $'9',$'0',R4,L2 # Цифра (преобразувай в ASCII спекулативно)? 13 0019 800754 ADDB2 $'A'-0xA-'0',R4 # Не, буква – преобразувай я в ASCII-код 14 001c 905482 L2: MOVB R4,(R2)+ # Запиши така получения ASCII-код в низа 15 001f E95303 BLBC R3,L3 # Нечетна тетрада (четна стойност на брояча)? 16 0022 902D82 MOVB $'-',(R2)+ # Не, запиши тирето като следващ символ в низа 17 0025 F553E2 L3: SOBGTR R3,L1 # Да, премини към следващата тетрада 18 0028 905372 MOVB R3,-(R2) # Замени шестото излишно тире с терминатор 0, 19 002b 04 RET # връщайки се с 1 назад към неговия адрес ==> we32k/putmacst.s <== # Write at an address passed in ap(8) -> r2 an ASCIIZ string in hexadecimal # format with a hyphen as a byte delimiter, obtained from a 48-bit MAC address # passed in ap(0):ap(4) -> r0:r1. section .text .globl putmacst putmacst() putmacst: 0: 10 47 SAVE %r7 #"AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 40 MOVW 0(%ap),%r0 # Programming Manual", pp. 6-13, 6-14 5: 84 74 41 MOVW 4(%ap),%r1 8: 84 78 42 MOVW 8(%ap),%r2 # r0:r1 = MAC address, r2 = string buffer addr. b: 87 0c 48 MOVB &12,%r8 # Initialise the nibble counter e: cc 03 0c 40 47 L1: EXTFW &3,&12,%r0,%r7 # Load a new nibble (from high to low) 13: d0 04 40 40 LLSW3 &4,%r0,%r0 # Shift the MAC address left by 1 nibble, 17: d8 1c 41 41 ROTW &28,%r1,%r1 # filling in the released intermediate nibble 1b: c8 03 00 41 40 INSFW &3,&0,%r1,%r0 20: 3f 0a 47 CMPB &0xA,%r7 # A letter from A to F? 23: 5b 05 BLUB L2 # No, it's a digit - just add ASCII '0' (0x30) 25: 9f 07 47 ADDB2 &0x41-0xA-0x30,%r7# Yes, convert considering next adding of '0' 28: df 30 47 52 L2: ADDB3 &0x30,%r7,(%r2) # Convert (finish conversion) to ASCII & write 2c: 70 NOP 2d: 90 42 INCW %r2 # Update the address 2f: 3b 01 48 BITB &1,%r8 # An even nibble (odd counter value)? 32: 7f 08 BEB L3 # No, continue with the low digit of this byte 34: 87 2d 52 MOVB &0x2D,(%r2) # Yes, write a delimiter (2D='-') to the string 37: 70 NOP 38: 90 42 INCW %r2 # Update the address 3a: 97 48 L3: DECB %r8 # Last nibble? 3c: 77 d2 BNEB L1 # No, go process the next one 3e: 87 48 c2 ff MOVB %r8,-1(%r2) # Yes, replace the 6th excessive hyphen with 0 42: 70 NOP 43: 04 c9 f0 4c MOVAW -16(%fp),%sp RESTORE %r7 # Restore the saved registers (r6-r8) 47: 20 48 POPW %r8 49: 20 47 POPW %r7 4b: 20 49 POPW %fp 4d: 08 RET # Return to the calling function 4e: 70 NOP 4f: 70 NOP 68K GAS putmacst.s page 1 1 | Да се напише подпрограма, която да записва от адрес, подаден в SP(12) -> A0, 2 | низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 | получен от 48-битов MAC-адрес, подаден в SP(4) -> D0:D1. 4 5 .global putmacst 6 putmacst: 7 0000 4CEF 0103 0004 MOVEML 4(%SP),%D0-%D1/%A0| D0:D1 = MAC-адрес, A0 = нач. адрес на низа 8 0006 48E7 3800 MOVEML %D2-%D4,-(%SP) | D2 = тетрада, D3 = брояч на тетрадите 9 000a 760B MOVEQ #11,%D3 | Инициализирай брояча на тетрадите (12 − 1) 10 000c 7869 MOVEQ #0x69,%D4 | Подготви умалителя за преобразуването в ASCII 11 000e E9C0 2404 L1: BFEXTU %D0{16:4},%D2 | Зареди нова тетрада (от старша към младша) 12 0012 0440 A000 SUBIW #0xA000,%D0 | Отличи цифрите (X = 1) от буквите (X = 0) 13 0016 8504 SBCD %D4,%D2 | 0-9 − 6A − 66 = 30-39, A-F − 69 − 60 = 41-46 14 0018 10C2 MOVEB %D2,(%A0)+ | Запиши така получения ASCII-код в низа 15 001a E948 LSLW #4,%D0 | Измести MAC-адреса в D0:D1 с 1 тетрада наляво 16 001c E999 ROLL #4,%D1 17 001e EFC0 1704 BFINS %D1,%D0{28:4} 18 0022 0803 0000 BTSTB #0,%D3 | Нечетна тетрада (нечетна стойност на брояча)? 19 0026 6604 BNEB L3 | Да, има още една в байта 20 0028 10FC 002D MOVEB #'-',(%A0)+ | Не, запиши тирето като следващ символ в низа 21 002c 51CB FFE0 L3: DBF %D3,L1 | Премини към следващата тетрада 22 0030 4220 CLRB -(%A0) | Замени шестото излишно тире с терминатор 23 0032 4CDF 001C MOVEML (%SP)+,%D2-%D4 | '\0', връщайки се с 1 назад към неговия адрес 24 0036 4E75 RTS x86 NASM putmacst.s 1 ; Да се напише подпрограма, която да записва от адрес, подаден в регистър ECX, 2 ; низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 ; получен от MAC-адрес, подаден в регистри EDX:EAX. 4 5 section .text 6 global putmacst,_putmacst ;в GCC декларирай с __attribute__((regparm(3))) 7 putmacst: 8 _putmacst: 9 00000000 60 PUSHAD ; GCC изисква EBX и EDI да се съхраняват 10 00000001 89CF MOV EDI,ECX ; Начален адрес на низа 11 00000003 93 XCHG EBX,EAX ; EBX = младша дума на MAC-адреса 12 00000004 B9AA0A0000 MOV ECX,0AAAH ; Инициализирай брояча на тетрадите 13 00000009 88F0 L1: MOV AL,DH ; Зареди нова тетрада (от старша към младша) 14 0000000B C0E804 SHR AL,4 15 0000000E 0FA4DA04 SHLD EDX,EBX,4 ; Измести MAC-адреса с 1 тетрада наляво 16 00000012 C1E304 SHL EBX,4 17 00000015 3C0A CMP AL,10 ; Отличи цифрите (CF = 1) от буквите (CF = 0) 18 00000017 1C69 SBB AL,69H ; 0-9 => 96H-9FH (AF = 1), AH-FH => A1H-A6H (AF = 0) 19 00000019 2F DAS ; Извади 66H от цифрите, а от буквите - 60H 20 0000001A AA STOSB ; Запиши така получения ASCII-код в низа 21 0000001B D1E9 SHR ECX,1 ; Четна тетрада? 22 0000001D 73EA JNC L1 ; Не, има още една 23 0000001F B02D MOV AL,'-' ; Да, подготви разделителя като следващ символ 24 00000021 AA STOSB ; и го запиши в низа 25 00000022 75E5 JNZ L1 ; Има и други байтове? Премини към следващия 26 00000024 884FFF MOV BYTE [EDI-1],CL ; Замени шестото излишно тире с терминатор 0 27 00000027 61 POPAD 28 00000028 C3 RET ARM GAS putmacst.s page 1 1 // Да се напише подпрограма, която да записва от адрес, подаден в регистър R2, 2 // низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 // получен от 48-битов MAC-адрес, подаден в регистри R1:R0. 4 5 .global putmacst 6 putmacst: 7 0000 38309FE5 LDR R3,=0xAAA // Инициализирай брояча на тетрадите 8 0004 21C6A0E1 L1: MOV R12,R1,LSR #12 // Зареди нова тетрада (от старша към младша) 9 0008 0FC00CE2 AND R12,R12,#0xF // Изолирай я 10 000c 0112A0E1 MOV R1,R1,LSL #4 // Измести MAC-адреса с 1 тетрада наляво 11 0010 201E81E1 ORR R1,R1,R0,LSR #28 12 0014 0002A0E1 MOV R0,R0,LSL #4 13 0018 0A005CE3 CMP R12,#0xA // Буква от A до F? 14 001c 37C08C22 ADDHS R12,R12,#'A'-0xA// Да, преобразувай я в ASCII-код 15 0020 30C08C32 ADDLO R12,R12,#'0' // Не, цифра е - преобразувай я в ASCII-код 16 0024 01C0C2E4 STRB R12,[R2],#1 // Запиши така получения ASCII-код в низа 17 0028 A330B0E1 MOVS R3,R3,LSR #1 // Четна тетрада? 18 002c 2DC0A023 MOVCS R12,#'-' // Да, подготви разделителя като следващ символ 19 0030 01C0C224 STRCSB R12,[R2],#1 // и го запиши в низа 20 0034 F2FFFF1A BNE L1 // Има и други байтове? Премини към следващия 21 0038 013042E5 STRB R3,[R2,#-1] // Замени шестото излишно тире с терминатор 22 003c 1EFF2FE1 BX LR // 0, връщайки се с 1 назад към неговия адрес 22 AA0A0000 ARC GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r2, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри r1:r0. 4 5 .global putmacst 6 putmacst: 7 0000 C343 0000 AA0A MOV_S r3,0xAAA # Инициализирай брояча на тетрадите 8 0006 2D21 8C0F 0000 6C00 L1: XBFU r12,r1,(4 - 1) << 5 | 12# Зареди тетрада (от старша към младша) 9 000e 3469 ASL_S r1,r1,4 # Измести MAC-адреса с 1 тетрада наляво 10 0010 4128 0407 LSR r4,r0,28 11 0014 0521 0101 OR r1,r1,r4 12 0018 1468 ASL_S r0,r0,4 13 001a 8AE4 CMP_S r12,0xA # Буква от A до F? 14 001c C024 E61D ADD.HS r12,r12,'A'-0xA # Да, преобразувай я в ASCII-код 15 0020 C024 251C ADD.LO r12,r12,'0' # Не, цифра е - преобразувай я в ASCII-код 16 0024 011A 1203 STB.AB r12,[r2,1] # Запиши така получения ASCII-код в низа 17 0028 2F23 C280 LSR.F r3,r3 # Четна тетрада? 18 002c 6DF7 BHS_S L1 # Не (няма пренос), премини към следващата 19 002e 2DDC MOV_S r12,'-' # Да, подготви разделителя като следващ символ 20 0030 011A 1203 STB.AB r12,[r2,1] # и го запиши в низа 21 0034 E9F5 BNE_S L1 # Има и други байтове? Премини към следващия 22 0036 FF1A C280 STB r3,[r2,-1] # Замени шестото излишно тире с терминатор 23 003a E07E J_S [blink] # 0, връщайки се с 1 назад към неговия адрес PPC GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r5, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри r3:r4. 4 5 .global putmacst 6 putmacst: 7 0000 38A5FFFF addi r5,r5,-1 # Компенсирай преинкрементната адресация 8 0004 38C0000C li r6,12 # Инициализирай брояча на тетрадите 9 0008 5467A73E L1: rlwinm r7,r3,20,28,31 # Зареди нова тетрада (от старша към младша) 10 000c 54632036 slwi r3,r3,4 # Измести MAC-адреса с 1 тетрада наляво, 11 0010 5083273E rlwimi r3,r4,4,28,31 # запълвайки освободената междинна тетрада 12 0014 54842036 slwi r4,r4,4 13 0018 2807000A cmplwi r7,0xA # Буква от A до F? 14 001c 41800008 blt L2 # Не, цифра е - само добави ASCII-кода на 0 15 0020 38E70007 addi r7,r7,'A-0xA-'0 # Да, преобразувай с отчитане добавянето на '0' 16 0024 38E70030 L2: addi r7,r7,'0 # Превърни (завърши преобразуването) в ASCII 17 0028 9CE50001 stbu r7,1(r5) # Запиши така получения ASCII-код в низа 18 002c 70C80001 andi. r8,r6,1 # Четна тетрада (нечетна стойност на брояча)? 19 0030 4182000C beq L3 # Не, продължи с младшата цифра на този байт 20 0034 38E0002D li r7,'- # Да, подготви разделителя като следващ символ 21 0038 9CE50001 stbu r7,1(r5) # и го запиши в низа 22 003c 34C6FFFF L3: addic. r6,r6,-1 # Последна тетрада? 23 0040 4082FFC8 bne L1 # Не, премини към обработка на следващата 24 0044 98C50000 stb r6,0(r5) # Да, замени шестото излишно тире с терминатор 25 0048 4E800020 blr # (след преинкрементната адресация r5 сочи там) SPARC GAS putmacst.s page 1 1 ! Да се напише подпрограма, която да записва от адрес, подаден в регистър %o2, 2 ! низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 ! получен от 48-битов MAC-адрес, подаден в регистри %o0:%o1. 4 5 .global putmacst 6 putmacst: 7 0000 9610200C mov 12,%o3 ! Инициализирай брояча на тетрадите 8 0004 9932200C L1: srl %o0,12,%o4 ! Зареди нова тетрада (от старша към младша) 9 0008 980B200F and %o4,0xF,%o4 ! Изолирай я 10 000c 912A2004 sll %o0,4,%o0 ! Измести MAC-адреса с 1 тетрада наляво, 11 0010 9B32601C srl %o1,28,%o5 ! запълвайки освободената междинна тетрада 12 0014 9012000D or %o0,%o5,%o0 13 0018 80A3200A cmp %o4,0xA ! Буква от A до F? 14 001c 0A800003 bcs L2 ! Не, цифра е - само добави ASCII-кода на 0 15 0020 932A6004 sll %o1,4,%o1 ! Измести младшата дума (изп. се преди „bcs“!) 16 0024 98032007 add %o4,'A'-0xA-'0',%o4! Да, превърни с отчитане добавянето на '0' 17 0028 98032030 L2: add %o4,'0',%o4 ! Превърни (завърши преобразуването) в ASCII 18 002c D82A8000 stb %o4,[%o2] ! Запиши така получения ASCII-код в низа 19 0030 9402A001 add %o2,1,%o2 ! Обнови адреса 20 0034 808AE001 andcc %o3,1,%g0 ! Четна тетрада (нечетна стойност на брояча)? 21 0038 02800004 be L3 ! Не, продължи с младшата цифра на този байт 22 003c 9810202D mov '-',%o4 ! Да, подготви разделителя като следващ символ 23 0040 D82A8000 stb %o4,[%o2] ! и го запиши в низа 24 0044 9402A001 add %o2,1,%o2 ! Обнови адреса 25 0048 96A2E001 L3: subcc %o3,1,%o3 ! Последна тетрада? 26 004c 12BFFFEE bne L1 ! Не, премини към обработка на следващата 27 0050 01000000 nop 28 0054 81C3E008 retl ! след „stb“ ! Да, замени шестото излишно тире с терминатор 29 0058 D62ABFFF stb %o3,[%o2-1] ! 0, връщайки се с 1 назад към неговия адрес MIPS GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър $6, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри $4:$5. 4 5 .ent putmacst 6 .global putmacst 7 putmacst: 8 0000 2407000C LI $7,12 # Инициализирай брояча на тетрадите 9 0004 7C881B00 L1: EXT $8,$4,12,4 # Зареди нова тетрада (от старша към младша) 10 0008 00042100 SLL $4,$4,4 # Измести MAC-адреса с 1 тетрада наляво, 11 000c 00252F02 ROTR $5,$5,28 # запълвайки освободената междинна тетрада 12 0010 7CA41804 INS $4,$5,0,4 13 0014 2D09000A SLTIU $9,$8,0xA # Буква от A до F? 14 0018 15200002 00000000 BNE $9,$0,L2 # Не, цифра е - само добави ASCII-кода на 0 15 0020 25080007 ADDIU $8,$8,'A'-0xA-'0'#Да, преобразувай с отчитане добавянето на '0' 16 0024 25080030 L2: ADDIU $8,$8,'0' # Превърни (завърши преобразуването) в ASCII 17 0028 A0C80000 SB $8,0($6) # Запиши така получения ASCII-код в низа 18 002c 24C60001 ADDIU $6,$6,1 # Обнови адреса 19 0030 30E90001 ANDI $9,$7,1 # Четна тетрада (нечетна стойност на брояча)? 20 0034 11200004 00000000 BEQ $9,$0,L3 # Не, продължи с младшата цифра на този байт 21 003c 2408002D LI $8,'-' # Да, подготви разделителя като следващ символ 22 0040 A0C80000 SB $8,0($6) # и го запиши в низа 23 0044 24C60001 ADDIU $6,$6,1 # Обнови адреса 24 0048 24E7FFFF L3: ADDIU $7,$7,-1 # Последна тетрада? 25 004c 14E0FFED 00000000 BNE $7,$0,L1 # Не, премини към обработка на следващата 26 SB $0,-1($6) # Да, замени шестото излишно тире с терминатор 27 0054 03E00008 A0C0FFFF JR $31 # 0, връщайки се с 1 назад към неговия адрес 28 005c 00000000 .end putmacst RISC-V GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър a2, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри a1:a0. 4 5 .global putmacst 6 putmacst: 7 0000 B146 LI a3,12 # Инициализирай брояча на тетрадите 8 0002 13D7C500 L1: SRLI a4,a1,12 # Зареди нова тетрада (от старша към младша) 9 0006 3D8B ANDI a4,a4,0xF # Изолирай я 10 0008 9205 SLLI a1,a1,4 # Измести MAC-адреса с 1 тетрада наляво, 11 000a 9357C501 SRLI a5,a0,28 # запълвайки освободената междинна тетрада 12 000e DD8D OR a1,a1,a5 13 0010 1205 SLLI a0,a0,4 14 0012 9337A700 SLTIU a5,a4,0xA # Буква от A до F? 15 0016 91E3 BNEZ a5,L2 # Не, цифра е - само добави ASCII-кода на 0 16 0018 1D07 ADDI a4,a4,'A'-0xA-'0'#Да, преобразувай с отчитане добавянето на '0' 17 001a 13070703 L2: ADDI a4,a4,'0' # Превърни (завърши преобразуването) в ASCII 18 001e 2300E600 SB a4,0(a2) # Запиши така получения ASCII-код в низа 19 0022 0506 ADDI a2,a2,1 # Обнови адреса 20 0024 93F71600 ANDI a5,a3,1 # Четна тетрада (нечетна стойност на брояча)? 21 0028 91C7 BEQZ a5,L3 # Не, продължи с младшата цифра на този байт 22 002a 1307D002 LI a4,'-' # Да, подготви разделителя като следващ символ 23 002e 2300E600 SB a4,0(a2) # и го запиши в низа 24 0032 0506 ADDI a2,a2,1 # Обнови адреса 25 0034 FD16 L3: ADDI a3,a3,-1 # Последна тетрада? 26 0036 F1F6 BNEZ a3,L1 # Не, премини към обработка на следващата 27 0038 A30F06FE SB x0,-1(a2) # Да, замени шестото излишно тире с терминатор 28 003c 8280 RET # 0, връщайки се с 1 назад към неговия адрес Nios II GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r6, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри r5:r4. 4 5 .global putmacst 6 putmacst: 7 0000 1403C001 MOVUI r7,12 # Инициализирай брояча на тетрадите 8 0004 3AD31028 L1: SRLI r8,r5,12 # Зареди нова тетрада (от старша към младша) 9 0008 CC030042 ANDI r8,r8,0xF # Изолирай я 10 000c 3A910A28 SLLI r5,r5,4 # Измести MAC-адреса с 1 тетрада наляво, 11 0010 3AD71220 SRLI r9,r4,28 # запълвайки освободената междинна тетрада 12 0014 3AB04A2A OR r5,r5,r9 13 0018 3A910820 SLLI r4,r4,4 14 001c B0024042 CMPLTUI r9,r8,0xA # Буква от A до F? 15 0020 1E010048 BNE r9,r0,L2 # Не, цифра е - само добави ASCII-кода на 0 16 0024 C4010042 ADDI r8,r8,'A'-0xA-'0'#Да, преобразувай с отчитане добавянето на '0' 17 0028 040C0042 L2: ADDI r8,r8,'0' # Превърни (завърши преобразуването) в ASCII 18 002c 05000032 STB r8,(r6) # Запиши така получения ASCII-код в низа 19 0030 44008031 ADDI r6,r6,1 # Обнови адреса 20 0034 4C00403A ANDI r9,r7,1 # Четна тетрада (нечетна стойност на брояча)? 21 0038 26030048 BEQ r9,r0,L3 # Не, продължи с младшата цифра на този байт 22 003c 540B0002 MOVUI r8,'-' # Да, подготви разделителя като следващ символ 23 0040 05000032 STB r8,(r6) # и го запиши в низа 24 0044 44008031 ADDI r6,r6,1 # Обнови адреса 25 0048 C4FFFF39 L3: SUBI r7,r7,1 # Последна тетрада? 26 004c 1EED3F38 BNE r7,r0,L1 # Не, премини към обработка на следващата 27 0050 C5FF3F30 STB r0,-1(r6) # Да, замени шестото излишно тире с терминатор 28 0054 3A2800F8 RET # 0, връщайки се с 1 назад към неговия адрес Xtensa GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър a4, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри a3:a2. 4 5 .global putmacst 6 putmacst: 7 0000 0CC5 MOVI a5,12 # Инициализирай брояча на тетрадите 8 0002 306C41 L1: SRLI a6,a3,12 # Зареди нова тетрада (от старша към младша) 9 0005 606034 EXTUI a6,a6,0,4 # Изолирай я 10 0008 C03311 SLLI a3,a3,4 # Измести MAC-адреса с 1 тетрада наляво, 11 000b 207C35 EXTUI a7,a2,28,4 # запълвайки освободената междинна тетрада 12 000e 703320 OR a3,a3,a7 13 0011 C02211 SLLI a2,a2,4 14 0014 B69601 BLTUI a6,10,L2 # Ако е цифра, само добави ASCII-кода на 0 15 0017 7B66 ADDI a6,a6,'A'-0xA-'0'# Преобразувай с отчитане добавянето на '0' 16 0019 62C630 L2: ADDI a6,a6,'0' # Превърни (завърши преобразуването) в ASCII 17 001c 624400 S8I a6,a4,0 # Запиши така получения ASCII-код в низа 18 001f 1B44 ADDI a4,a4,1 # Обнови адреса 19 0021 076507 BBCI a5,0,L3 # Четна тетрада (нечетна стойност на брояча)? 20 0024 2CD6 MOVI a6,'-' # Да, подготви разделителя като следващ символ 21 0026 624400 S8I a6,a4,0 # и го запиши в низа 22 0029 42C401 ADDI a4,a4,1 # Обнови адреса 23 002c 0B55 L3: ADDI a5,a5,-1 # Последна тетрада? 24 002e 5605FD BNEZ a5,L1 # Не, премини към обработка на следващата 25 0031 0B44 ADDI a4,a4,-1 # Да, замени шестото излишно тире с терминатор 26 0033 524400 S8I a5,a4,0 # 0, връщайки се с 1 назад към неговия адрес 27 0036 0DF0 RET 88K GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър r4, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри r2:r3. 4 5 .global _putmacst 6 0000 58A0000B _putmacst: 7 0004 F0C2988C or r5,r0,11 # Инициализирай брояча на тетрадите (до −1!) 8 0008 F042A004 L1: extu r6,r2,4<12> # Зареди нова тетрада (от старша към младша) 9 000c F0E3989C mak r2,r2,0<4> # Измести MAC-адреса с 1 тетрада наляво, 10 0010 F063A004 extu r7,r3,4<28> # запълвайки освободената междинна тетрада 11 0014 F4475802 mak r3,r3,0<4> 12 0018 7CE6000A or r2,r7,r2 13 001c D9470002 cmp r7,r6,0xA # Буква от A до F? 14 0020 60C60007 bb1 lo,r7,L2 # Не, цифра е - само добави ASCII-кода на 0 15 0024 60C60030 addu r6,r6,'A'-0xA-'0'# Да, превърни с отчитане добавянето на '0' 16 0028 F4C42C00 L2: addu r6,r6,'0' # Превърни (завърши преобразуването) в ASCII 17 002c 60840001 st.b r6,r4,r0 # Запиши така получения ASCII-код в низа 18 0030 D8050004 addu r4,r4,1 # Обнови адреса 19 0034 58C0002D bb1 0,r5,L3 # При четна тетрада (четна стойност на брояча) 20 0038 F4C42C00 or r6,r0,'-' # подготви разделителя като следващ символ 21 003c 60840001 st.b r6,r4,r0 # и го запиши в низа 22 0040 64A50001 addu r4,r4,1 # Обнови адреса 23 0044 E865FFF0 L3: subu r5,r5,1 # Последна тетрада? 24 0048 F4042C05 bcnd ge0,r5,L1 # Не, премини към обработка на следващата 25 004c F400C001 st.b r0,r4,r5 # Да, замени шестото излишно тире с терминатор jmp r1 # 0, връщайки се с 1 назад към неговия адрес Or1k GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър R5, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри R3:R4. 4 5 .global putmacst 6 putmacst: 7 0000 A8C0000C L.ORI R6,R0,12 # Инициализирай брояча на тетрадите 8 0004 B8E3004C L1: L.SRLI R7,R3,12 # Зареди нова тетрада (от старша към младша) 9 0008 A4E7000F L.ANDI R7,R7,0xF # Изолирай я 10 000c B8630004 L.SLLI R3,R3,4 # Измести MAC-адреса с 1 тетрада наляво, 11 0010 B904005C L.SRLI R8,R4,28 # запълвайки освободената междинна тетрада 12 0014 E0634004 L.OR R3,R3,R8 13 0018 BC67000A L.SFGEUI R7,0xA # Буква от A до F? 14 001c 0C000003 L.BNF L2 # Не, цифра е - само добави ASCII-кода на 0 15 0020 B8840004 L.SLLI R4,R4,4 # Измести младшата дума (изп.се преди „L.BNF“!) 16 0024 9CE70007 L.ADDI R7,R7,'A'-0xA-'0' # Да, превърни с отчитане добавянето на '0' 17 0028 9CE70030 L2: L.ADDI R7,R7,'0' # Превърни (завърши преобразуването) в ASCII 18 002c D8053800 L.SB 0(R5),R7 # Запиши така получения ASCII-код в низа 19 0030 9CA50001 L.ADDI R5,R5,1 # Обнови адреса 20 0034 A5060001 L.ANDI R8,R6,1 21 0038 E4080000 L.SFEQ R8,R0 # Четна тетрада (нечетна стойност на брояча)? 22 003c 10000004 L.BF L3 # Не, продължи с младшата цифра на този байт 23 0040 A8E0002D L.ORI R7,R0,'-' # Да, подготви разделителя като следващ символ 24 0044 D8053800 L.SB 0(R5),R7 # и го запиши в низа 25 0048 9CA50001 L.ADDI R5,R5,1 # Обнови адреса 26 004c 9CC6FFFF L3: L.ADDI R6,R6,-1 # Последна тетрада? 27 0050 E4060000 L.SFEQ R6,R0 28 0054 0FFFFFEC L.BNF L1 # Не, премини към обработка на следващата 29 0058 15000000 L.NOP 0 30 005c 44004800 L.JR LR# след „L.SB“ # Да, замени шестото излишно тире с терминатор 31 0060 DBE537FF L.SB -1(R5),R6 # 0, връщайки се с 1 назад към неговия адрес Xilinx MicroBlaze GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър R7, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри R6:R5. 4 5 .global putmacst 6 putmacst: 7 0000 0C0000A1 ORI R8,R0,12 # Инициализирай брояча на тетрадите 8 0004 0C002665 L1: BSRLI R9,R6,12 # Зареди нова тетрада (от старша към младша) 9 0008 0F0029A5 ANDI R9,R9,0xF # Изолирай я 10 000c 0404C664 BSLLI R6,R6,4 # Измести MAC-адреса с 1 тетрада наляво, 11 0010 1C006564 BSRLI R3,R5,28 # запълвайки освободената междинна тетрада 12 0014 0018C680 OR R6,R6,R3 13 0018 0404A564 BSLLI R5,R5,4 14 001c F6FF6920 ADDI R3,R9,-0xA # Буква от A до F? 15 0020 080043BC BLTI R3,L2 # Не, цифра е - само добави ASCII-кода на 0 16 0024 07002921 ADDI R9,R9,'A'-0xA-'0'# Да, преобразувай с отчитане добавянето на '0' 17 0028 30002921 L2: ADDI R9,R9,'0' # Превърни (завърши преобразуването) в ASCII 18 002c 000027F1 SBI R9,R7,0 # Запиши така получения ASCII-код в низа 19 0030 0100E720 ADDI R7,R7,1 # Обнови адреса 20 0034 010068A4 ANDI R3,R8,1 # Четна тетрада (нечетна стойност на брояча)? 21 0038 100003BC BEQI R3,L3 # Не, продължи с младшата цифра на този байт 22 003c 2D0020A1 ORI R9,R0,'-' # Да, подготви разделителя като следващ символ 23 0040 000027F1 SBI R9,R7,0 # и го запиши в низа 24 0044 0100E720 ADDI R7,R7,1 # Обнови адреса 25 0048 FFFF0821 L3: ADDI R8,R8,-1 # Последна тетрада? 26 004c B8FF28BC BNEI R8,L1 # Не, премини към обработка на следващата 27 0050 08000FB6 RTSD R15,8 # (върни управлението; изпълн. се след „SBI“!) 28 0054 FFFF07F1 SBI R8,R7,-1 # Да, замени шестото излишно тире с терминатор HPPA GAS putmacst.s page 1 1 ; Да се напише подпрограма, която да записва от адрес, подаден в регистър %R24, 2 ; низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 ; получен от 48-битов MAC-адрес, подаден в регистри %R25:%R26. 4 5 .text 6 .global putmacst 7 putmacst: ; %R23 = брояч на тетрадите, %R22 = тетрада 8 0000 3415005A LDI '-,%R21 ; Подготви разделителя между байтовете 9 0004 34170018 LDI 12,%R23 ; Инициализирай брояча на тетрадите 10 0008 D3361A7C L1: EXTRU %R25,19,4,%R22 ; Зареди нова тетрада (от старша към младша) 11 000c D7390C84 DEP %R25,27,28,%R25 ; Измести MAC-адреса с 1 тетрада наляво 12 0010 D35A087A SHD %R26,%R26,28,%R26 13 0014 D73A0C1C DEP %R26,31,4,%R25 14 0018 92C07014 COMICLR,> 10,%R22,%R0 ; Цифра ли е тетрадата? 15 001c B6D6000E ADDI 'A-'0-10,%R22,%R22; Не, буква – преобразувай в ASCII в 2 стъпки 16 0020 B6D60060 ADDI '0,%R22,%R22 ; Да, – превърни в ASCII (II стъпка за букви) 17 0024 0F161222 STBS,MA %R22,1(%R24) ; Запиши така получения ASCII-код в низа 18 0028 0AF7F240 OR,EV %R23,%R23,%R0 ; Нечетна тетрада (четна стойност на брояча)? 19 002c 0F151222 STBS,MA %R21,1(%R24) ; Не, запиши тирето като следващ символ в низа 20 0030 AEFF3FA5 ADDIBF,= -1,%R23,L1 ; Да, премини към следващата тетрада 21 0034 08000240 NOP 22 0038 E840C000 BV (%R2) ; Замени шестото излишно тире с терминатор 0, 23 003c 0F17323F STBS,MB %R23,-1(%R24) ; връщайки се с 1 назад към неговия адрес Renesas / SuperH SH GAS Little Endian putmacst.s page 1 1 ! Да се напише подпрограма, която да записва от адрес, подаден в регистър R6, 2 ! низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 ! получен от 48-битов MAC-адрес, подаден в регистри R5:R4. 4 5 .global putmacst 6 putmacst: 7 0000 0CE3 MOV #12,R3 ! Инициализирай брояча на тетрадите 8 0002 04E7 MOV #4,R7 ! За лявото изместване с 4 разреда 9 0004 5360 L1: MOV R5,R0 10 0006 F4E1 MOV #-12,R1 ! Измествай с 12 разреда надясно 11 0008 1D40 SHLD R1,R0 ! Зареди нова тетрада (от старша към младша) 12 000a 0FC9 AND #0xF,R0 ! Изолирай я 13 000c 7D45 SHLD R7,R5 ! Измести MAC-адреса с 1 тетрада наляво, 14 000e 4362 MOV R4,R2 ! запълвайки освободената междинна тетрада: 15 0010 E4E1 MOV #-28,R1 ! Измествай с 28 разреда надясно 16 0012 1D42 SHLD R1,R2 ! Направи най-старшата тетрада най-младша 17 0014 2B25 OR R2,R5 ! Копирай я на освободеното място 18 0016 7D44 SHLD R7,R4 ! Измести и младшата дума 19 0018 0AE1 MOV #0xA,R1 20 001a 1230 CMP/HS R1,R0 ! Буква от A до F? 21 001c 008B BF L2 ! Не, цифра е - само добави ASCII-кода на 0 22 001e 0770 ADD #'A'-0xA-'0',R0 ! Да, превърни с отчитане добавянето на '0' 23 0020 3070 L2: ADD #'0',R0 ! Превърни (завърши преобразуването) в ASCII 24 0022 0026 MOV.B R0,@R6 ! Запиши така получения ASCII-код в низа 25 0024 0176 ADD #1,R6 ! Обнови адреса 26 0026 3360 MOV R3,R0 27 0028 01C8 TST #1,R0 ! Четна тетрада (нечетна стойност на брояча)? 28 002a 0289 BT L3 ! Не, продължи с младшата цифра на този байт 29 002c 2DE0 MOV #'-',R0 ! Да, подготви разделителя като следващ символ 30 002e 0026 MOV.B R0,@R6 ! и го запиши в низа 31 0030 0176 ADD #1,R6 ! Обнови адреса 32 0032 1043 L3: DT R3 ! Последна тетрада? 33 0034 E68B BF L1 ! Не, премини към обработка на следващата 34 0036 0B00 RTS ! Да, замени шестото излишно тире с терминатор 35 0038 3426 MOV.B R3,@-R6 ! 0, връщайки се с 1 назад към неговия адрес GAS for CRIS putmacst.s page 1 1 ; Да се напише подпрограма, която да записва от адрес, подаден в регистър $R12, 2 ; низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 ; получен от 48-битов MAC-адрес, подаден в регистри $R11:$R10. 4 5 .global putmacst 6 putmacst: 7 0000 4CD2 MOVEQ 12,$R13 ; Инициализирай брояча на тетрадите 8 0002 6B96 L1: MOVE.D $R11,$R9 9 0004 EC93 LSRQ 12,$R9 ; Зареди нова тетрада (от старша към младша) 10 0006 0F93 ANDQ 0xF,$R9 ; Изолирай я 11 0008 C4B3 LSLQ 4,$R11 ; Измести MAC-адреса с 1 тетрада наляво, 12 000a 6AF6 MOVE.D $R10,$R15 ; запълвайки освободената междинна тетрада 13 000c FCF3 LSRQ 28,$R15 14 000e 4FB7 OR.B $R15,$R11 15 0010 CA92 CMPQ 0xA,$R9 ; Буква от A до F? 16 0012 0610 BLO L2 ; Не, цифра е - само добави ASCII-кода на 0 17 0014 C4A3 LSLQ 4,$R10 ; Измести младшата дума (изп. се преди „BLO“!) 18 0016 0792 ADDQ 'A'-0xA-'0',$R9 ; Да, превърни с отчитане добавянето на '0' 19 0018 3092 L2: ADDQ '0',$R9 ; Превърни (завърши преобразуването) в ASCII 20 001a CC9F MOVE.B $R9,[$R12+] ; Запиши ASCII-кода в низа и обнови адреса 21 001c 80D3 BTSTQ 0,$R13 ; Четна тетрада (нечетна стойност на брояча)? 22 001e 0860 BPL L3 ; Не, продължи с младшата цифра на този байт 23 0020 4F9E2D00 MOVE.B '-',$R9 ; Да, подготви разделителя като следващ символ, 24 0024 CC9F MOVE.B $R9,[$R12+] ; запиши го в низа и обнови адреса 25 0026 81D2 L3: SUBQ 1,$R13 ; Последна тетрада? 26 0028 DB20 BNE L1 ; Не, премини към обработка на следващата 27 002a FFC1 ADDO -1,$R12,$ACR ; (изпълнява се преди „BNE“, но нищо!) 28 002c F0B9 RET ; след „MOVE“ ; Да, замени шестото излишно тире с терминатор 29 002e CFDB MOVE.B $R13,[$ACR] ; 0, връщайки се с 1 назад към неговия адрес BFIN GAS putmacst.s page 1 1 # Да се напише подпрограма, която да записва от адрес, подаден в регистър R2, 2 # низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 # получен от 48-битов MAC-адрес, подаден в регистри R1:R0. 4 5 .global _putmacst 6 _putmacst: 7 0000 0232 P0 = R2; # Адресът на буфера – в адресен регистър 8 0002 6168 P1 = 12; # Задай брой итерации в брояча на тетрадите 9 0004 A2E01510 LSETUP (L_1, L_3) LC0 = P1;# LC0 и начален и краен адрес на цикъла 10 0008 82C68184 L_1: R2 = R1 << 16; # Изолирай в R2 тетрадата от битове 15–12 на R1 11 000c E24E R2 >>= 28; # (R1:xxxxTxxx -> R2:Txxx0000 -> R2:0000000T) 12 000e 214F R1 <<= 4; # Измести MAC-адреса с 1 тетрада наляво, 13 0010 82C62087 R3 = R0 >> 28; # запълвайки освободената междинна тетрада 14 0014 5956 R1 = R1 | R3; 15 0016 204F R0 <<= 4; 16 0018 5360 R3 = 10 (X); 17 001a 9A08 CC = R2 < R3; # Цифра? 18 001c 0218 IF CC JUMP L_2; # Да, само добави ASCII-кода на 0 19 001e 3A64 R2 += 'A'-0xA-'0'; # Не, преобразувай с отчитане добавянето на '0' 20 0020 8265 L_2: R2 += '0'; # Превърни (завърши преобразуването) в ASCII 21 0022 029A B [P0++] = R2; # Запиши този ASCII-код в низа и обнови адреса 22 0024 9831 R3 = LC0; 23 0026 0349 CC = BITTST(R3, 0); # Четна тетрада (нечетна стойност на брояча)? 24 0028 0310 IF !CC JUMP L_3; # Не, прескочи 25 002a 6B61 R3 = '-' (X); # Да, подготви разделителя като следващ символ 26 002c 039A B [P0++] = R3; # и го запиши в низа, обновявайки адреса 27 002e DB58 L_3: R3 = R3 ^ R3; # Замени шестото излишно тире с терминатор 0, 28 0030 83E6FFFF B [P0 - 1] = R3; # връщайки се с 1 назад към неговия адрес 29 0034 10000000 RTS; Hexagon GAS putmacst.s page 1 1 // Да се напише подпрограма, която да записва от адрес, подаден в регистър R2, 2 // низ тип ASCIIZ в шестнадесетичен формат с разделител между байтовете тире, 3 // получен от 48-битов MAC-адрес, подаден в регистри R1:R0. 4 5 .global putmacst 6 putmacst: 7 { R5 = #'-' // Подготви ASCII-кода на разделителя 8 0000 A5450078 43D50578 R3 = #0xAAA } // Инициализирай брояча на тетрадите 9 L1: { R4 = EXTRACTU(R1,#4,#12)//Зареди нова тетрада (от старша към младша) 10 0008 8444218D 40C40080 R1:0 = ASL(R1:0,#4) } // Измести MAC-адреса с 1 тетрада наляво 11 { P0 = CMP.GEU(R4,#0xA)// Буква от A до F? 12 IF (P0.NEW) R4 = ADD(R4,#'A'-0xA) // Да, преобразувай я в ASCII-код 13 0010 20418475 E4660474 04E68474 IF (!P0.NEW) R4 = ADD(R4,#'0') }// Не, цифра – " " " " " " 14 { MEMB(R2++#1) = R4 // Запиши ASCII-кода в низа и обнови адреса 15 P0 = TSTBIT(R3,#0) // Четна тетрада? 16 001c 00400385 2341038C 08C402AB R3 = LSR(R3,#1) } // (обнови брояча) 17 { IF (P0) MEMB(R2++#1) = R5//Да, запиши разделител в низа и обнови адреса 18 0028 F07F2361 08E502AB IF (R3!=#0) JUMP:T L1 } // Има и други байтове? Премини към следващия 19 { MEMB(R2+#-1) = R3 // Замени шестото излишно тире с терминатор 20 0030 00409F52 FFE302A7 JUMPR LR } // 0, връщайки се с 1 назад към неговия адрес S/390 GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър 2 частното, а на адрес, 2 # подаден в регистър 5, да записва остатъка от деленето на числото в регистри 3 # 2:3 на числото в регистър 4. 4 5 .global udiv64 6 udiv64: 7 0000 B9970024 DLR 2,4 # Рег. 3 = частно, рег. 2 = остатък 8 0004 50205000 ST 2,0(5) # Запиши остатъка на посочения адрес 9 0008 1823 LR 2,3 # Върни частното в рег. 2 10 000a 07FE BR 14 ==> id32/udiv64.s <== 1 * Return in register 0 the quotient, and write at the address passed in 7(12) 2 * the remainder of the division of the number in 7(0):7(4) -> registers 1:0 to 3 * the number in 7(8) -> register 2. 4 5 * ID32 lacks addition/subtraction with carry, so we don't use the CPU's C flag. 6 7 entry udiv64 http://codereview.stackexchange.com/questions/67962 00000000d 8 udiv64 equ * 00000d 5817 0000 9 l 1,0(7) Registers: 1:0 = dividend (a), 2 = divisor (b), 00004d 5807 0004 10 l 0,4(7) 3 = temp, 4 = carry, 5 = counter 00008d 5827 0008 11 l 2,8(7) 0000Cd 0744 12 xr 4,4 0000Ed C850 0021 13 lhi 5,33(0) _q = a_lo << 1; carry = a_lo >> 31; 00012d 230D 0000002Cd 14 bs L3 __/(r = a_hi;)// no need of separate q and r 00014d 0831 15 L1 lr 3,1 temp = r 00016d EC30 001F 16 srl 3,31(0) >> 31; 0001Ad 1111 17 slls 1,1 r = r<<1 0001Cd 0614 18 or 1,4 | carry; 0001Ed 0843 19 lr 4,3 carry = temp; 00020d 0644 20 or 4,4 00022d 2134 0000002Ad 21 bnzs L2 if (!carry) { 00024d 0512 22 clr 1,2 if (r < b) 00026d 2183 0000002Cd 23 bls L3 goto shift; 00028d 2641 24 ais 4,1 carry++; 0002Ad 0B12 25 L2 sr 1,2 } r -= b; 0002Cd 0830 26 L3 lr 3,0 shift:temp = q 0002Ed EC30 001F 27 srl 3,31(0) >>31; 00032d 1101 28 slls 0,1 q = q<<1 00034d 0604 29 or 0,4 | carry; 00036d 0843 30 lr 4,3 carry = temp; 00038d 2751 31 sis 5,1 Next iteration 0003Ad 4230 FFD6 00000014d 32 bnz L1(0) 0003Ed 5827 000C 33 l 2,12(7) *rem 00042d 5012 0000 34 st 1,0(2) = r; 00046d 030F 35 br 15 return q; VAX GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 частното, а на 2 # адрес, подаден в AP(16) -> R3, да записва остатъка от деленето на числото в 3 # AP(4) -> R1:R0 на числото в AP(12) -> R2. 4 5 .global _udiv64 # http://codereview.stackexchange.com/questions/67962 6 _udiv64: 7 0000 1C00 .word 0x1C # R2-R4; командата CALLS вече е нулирала флаг C 8 0002 FD7DAC04 50 MOVO 4(AP),R0# R1:R0 = делимо, R2 = делител, R3 = адрес на остатъка 9 0007 D02154 MOVL $33,R4 # Брч __q = a_lo << 1; carry = a_lo >> 31; 10 000a 110F BRB L3 # ___/ (r = a_hi;)//няма нужда от отделни q и r 11 000c D85151 L1: ADWC R1,R1 # temp = r>>31; r = r<<1 | carry; carry = temp; 12 000f 1F05 BCS L2 # if(!carry) { 13 0011 D15251 CMPL R2,R1 # if (r < b) 14 0014 1A05 BGTRU L3 # C = 0 goto shift; 15 0016 C25251 L2: SUBL2 R2,R1 # C = 1 (carry++;) } r -= b; 16 0019 B801 BISPSW $1 # Възстанови C 17 001b D85050 L3: ADWC R0,R0 # shift: temp=q>>31; q=q<<1|carry; carry=temp; 18 001e F554EB SOBGTR R4,L1 # Следваща итерация на цикъла 19 0021 D05163 MOVL R1,(R3) # *rem = r; 20 0024 04010101 RET # return q; //Възстанови и върни q в R0 ==> we32k/udiv64.s <== # Return in the r1 register the quotient, and write at the address passed in # ap(12) the remainder of the division of the number in ap(0):ap(4) -> r1:r0 # to the number in ap(8) -> r2. # WE32K lacks addition/subtraction with carry, so we don't use the CPU's C flag section .text .globl udiv64 # http://codereview.stackexchange.com/questions/67962 udiv64() udiv64: 0: 10 46 SAVE %r6 #"AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 41 MOVW 0(%ap),%r1 # Programming Manual", pp. 6-13, 6-14 5: 84 74 40 MOVW 4(%ap),%r0 # r1:r0 = dividend (a), r2 = divisor (b) 8: 84 78 42 MOVW 8(%ap),%r2 # r6 = temp, r7 = carry, r8 = counter b: 70 NOP c: 80 47 CLRW %r7 e: 84 21 48 MOVW &33,%r8 # _q = a_lo << 1; carry = a_lo >> 31; 11: 7b 1e BRB L3 #_/(r = a_hi;)// no need of separate q and r 13: d4 1f 41 46 L1: LRSW3 &31,%r1,%r6# temp = r >> 31; 17: d0 01 41 41 LLSW3 &1,%r1,%r1# r = r<<1 1b: b0 47 41 ORW2 %r7,%r1 # | carry; 1e: 84 46 47 MOVW %r6,%r7 # carry = temp; 21: 28 47 TSTW %r7 23: 77 09 BNEB L2 # if (!carry) { 25: 3c 42 41 CMPW %r2,%r1 # if (r < b) 28: 5b 07 BLUB L3 # goto shift; 2a: 90 47 INCW %r7 # carry++; 2c: bc 42 41 L2: SUBW2 %r2,%r1 # } r -= b; 2f: d4 1f 40 46 L3: LRSW3 &31,%r0,%r6#shift:temp = q>>31; 33: d0 01 40 40 LLSW3 &1,%r0,%r0# q = q<<1 37: b0 47 40 ORW2 %r7,%r0 # | carry; 3a: 84 46 47 MOVW %r6,%r7 # carry = temp; 3d: 97 48 DECB %r8 #Next iteration 3f: 77 d4 BNEB L1 41: 84 41 da 0c MOVW %r1,*12(%ap)#*rem = r; 45: 70 NOP 46: 04 c9 f4 4c MOVAW -12(%fp),%sp RESTORE %r6 4a: 20 48 POPW %r8 4c: 20 47 POPW %r7 4e: 20 46 POPW %r6 50: 20 49 POPW %fp 52: 08 RET # return q; 53: 70 NOP 68K GAS udiv64.s page 1 1 | Да се напише подпрограма, която да връща в регистър D0 частното, а на адрес, 2 | подаден в SP(16) (арг. №3), да записва остатъка от деленето на числото в 3 | SP(4) -> D0:D1 на числото в SP(12). 4 5 .global udiv64 6 udiv64: 7 0000 4CEF 0003 0004 MOVEML 4(%SP),%D0-%D1 | Делимо (в M68K двойно по-дълго от делителя) 8 0006 4C6F 1400 000C DIVUL 12(%SP),%D0:%D1 | D0 = остатък, D1 = частно 9 000c 2F80 0161 0010 MOVEL %D0,([16,%SP]) | Запиши остатъка 10 0012 2001 MOVEL %D1,%D0 | Върни частното в D0 11 0014 4E75 RTS x86 NASM udiv64.s 1 ; Да се напише подпрограма, която да връща в регистър EAX частното, а на адрес, 2 ; подаден в [ESP+4] (арг. №3), да записва остатъка от деленето на числото в 3 ; регистри EDX:EAX на числото в регистър ECX. 4 5 section .text 6 global udiv64,_udiv64 7 udiv64: 8 _udiv64: 9 00000000 F7F1 DIV ECX ; В x86 делимото е двойно по-дълго от делителя 10 00000002 8B4C2404 MOV ECX,[ESP+4] ; Адрес на остатъка 11 00000006 8911 MOV [ECX],EDX ; Запиши остатъка 12 00000008 C3 RET ; Върни частното в EAX ARM GAS udiv64.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 частното, а на адрес, 2 // подаден в регистър R3, да записва остатъка от деленето на числото в регистри 3 // R1:R0 на числото в регистър R2. 4 5 .global udiv64 // http://codereview.stackexchange.com/questions/67962 6 udiv64: 7 0000 30402DE9 STMFD SP!,{R4,R5,LR} //Съхрани използваните регистри: ARM IHI 0042F 8 0004 2140A0E3 MOV R4,#33 //Брч _q = a_lo << 1; carry = a_lo >> 31; 9 0008 0CF09FE2 ADDS PC,PC,#L2-(.+8) //C=0_/(r = a_hi;)//няма нужда от отделни q и r 10 000c 05F028E1 L1: MSR CPSR_f,R5 //Възстанови C temp = r >> 31; r = r << 1 | 11 0010 0110B1E0 ADCS R1,R1,R1 // carry; carry = temp; if(!carry) 12 0014 02005131 CMPCC R1,R2 // { if (r < b) goto shift; 13 0018 02104120 SUBHS R1,R1,R2 // C = 1 (carry++;) } r -= b; 14 001c 0000B0E0 L2: ADCS R0,R0,R0 // shift: temp = q >> 31; q = 15 0020 00500FE1 MRS R5,CPSR // Съхрани C q << 1 | carry; carry = temp; 16 0024 014054E2 SUBS R4,R4,#1 // Следваща итерация на цикъла? 17 0028 F7FFFF1A BNE L1 // Да, продължи 18 002c 001083E5 STR R1,[R3] // *rem = r; 19 0030 3080BDE8 LDMFD SP!,{R4,R5,PC} // return q; //Възстанови и върни q в R0 ARC GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r0 частното, а на адрес, 2 # подаден в регистър r3, да записва остатъка от деленето на числото в регистри 3 # r1:r0 на числото в регистър r2. 4 5 .global udiv64 # http://codereview.stackexchange.com/questions/67962 6 udiv64: 7 0000 4A24 0078 MOV lp_count,32 #Брч __q = a_lo << 1; carry = a_lo >> 31; 8 0004 2F20 0080 ASL.F r0,r0 #___/ (r = a_hi;)//няма нужда от отделни q и r 9 0008 A820 0003 LP L3 # Задай цикъла _temp = r >> 31; r = r << 1 | 10 000c 2F21 4B80 RLC.F r1,r1 #_____________/_carry; carry = temp; 11 0010 85F7 BLO_S L1 # if (!carry) { 12 0012 0D09 8400 BRLO r1,r2,L2 # if (r < b) goto shift; 13 0016 4E23 3E80 RSUB.F 0,r3,0 #______________ carry++; } r -= b; 14 001a 4279 L1: SUB_S r1,r1,r2 #____/ shift: _temp = q >> 31; q = 15 001c 2F20 0B80 L2: RLC.F r0,r0 #_____________/_q << 1 | carry; carry = temp; 16 0020 20A3 L3: ST_S r1,[r3] # *rem = r; 17 0022 E07E J_S [blink] # return q; //Върни q в r0 PPC GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r3 частното, а на адрес, 2 # подаден в регистър r6, да записва остатъка от деленето на числото в регистри 3 # r3:r4 на числото в регистър r5. 4 5 .global udiv64 # http://codereview.stackexchange.com/questions/67962 6 udiv64: 7 0000 39000000 li r8,0 # Ще потрябва за проверка на преноса 8 0004 34E80021 addic. r7,r8,33#CA=0, 33 итерации 9 0008 7CE903A6 mtctr r7 # _q = a_lo << 1; carry = a_lo >> 31; 10 000c 48000020 b L3 #_/(r = a_hi;)// няма нужда от отделни q и r 11 0010 7C631914 L1: adde r3,r3,r3# temp = r >> 31; r = r<<1 | carry; carry = temp; 12 0014 7CE801D5 addme. r7,r8 #CA-1=? (запази CA) 13 0018 41820010 beq L2 # if (!carry) { 14 001c 7C032840 cmplw r3,r5 # if (r < b) 15 0020 7CE51810 subfc r7,r5,r3#обн.CA 16 0024 41800008 blt L3 # goto shift; 17 0028 7C651850 L2: subf r3,r5,r3#CA=1 (carry++;) } r -= b; 18 002c 7C842114 L3: adde r4,r4,r4#shift: temp = q>>31; q = q<<1 | carry; carry = temp; 19 0030 4200FFE0 bdnz L1 # Следваща итерация 20 0034 90660000 stw r3,0(r6)# *rem = r; 21 0038 7C832378 mr r3,r4 # return q; 22 003c 4E800020 blr SPARC GAS udiv64.s page 1 1 ! Да се напише подпрограма, която да връща в регистър %o0 частното, а на адрес, 2 ! подаден в регистър %o3, да записва остатъка от деленето на числото в регистри 3 ! %o0:%o1 на числото в регистър %o2. 4 5 .global udiv64 6 udiv64: 7 0000 81822000 wr %o0,0,%y ! Подготви старшата дума на делимото 8 0004 01000000 nop ! Съгл. SAV080SI9308, стр. 134, предпоследния абзац, WRY е т.н. 9 0008 01000000 nop ! „delayed-write“. Но съгл. SAV09R1459912, стр. 245, абзац 5, 10 000c 01000000 nop ! това вече не е така при v9. И все пак ние компилираме за v8. 11 0010 9072400A udiv %o1,%o2,%o0 ! Върни частното в %o0 12 0014 94528008 umul %o2,%o0,%o2 13 0018 9222400A sub %o1,%o2,%o1 ! Получи остатъка (пренебрегвайки преноса) 14 001c 81C3E008 retl ! (изпълнява се след „st“!) 15 0020 D222C000 st %o1,[%o3] ! и го запиши на посочения адрес MIPS GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър $2 частното, а на адрес, 2 # подаден в регистър $7, да записва остатъка от деленето на числото в регистри 3 # $4:$5 на числото в регистър $6. 4 5 .ent udiv64 # http://codereview.stackexchange.com/questions/67962 6 .global udiv64 7 udiv64: # q = a_lo<<1;(r = a_hi;)//няма нужда от отделни q, r 8 0000 00054FC2 SRL $9,$5,31# /carry = a_lo >> 31; 9 0004 00052840 SLL $5,$5,1 #_/ 10 0008 24080020 LI $8,32 #брч 11 000c 00041FC2 L1: SRL $3,$4,31# temp = r >> 31; 12 0010 00042040 SLL $4,$4,1 # r = r << 1 13 0014 00892025 OR $4,$4,$9# | carry; 14 0018 00604821 MOVE $9,$3 # carry = temp; 15 001c 15200005 00000000 BNE $9,$0,L2# if (carry == 0) { 16 0024 0086082B 14200003 00000000 BLTU $4,$6,L3# if (r < b) goto shift; 17 0030 25290001 ADDIU $9,$9,1 # carry++; 18 0034 00862023 L2: SUBU $4,$4,$6# } r -= b; 19 0038 00051FC2 L3: SRL $3,$5,31#shift: temp = q >> 31; 20 003c 00052840 SLL $5,$5,1 # q = q << 1 21 0040 00A92825 OR $5,$5,$9# | carry; 22 0044 00604821 MOVE $9,$3 # carry = temp; 23 0048 2508FFFF ADDIU $8,$8,-1#Следваща 24 004c 1500FFEF 00000000 BNE $8,$0,L1#итерация 25 0054 ACE40000 SW $4,0($7)# *rem = r; 26 MOVE $2,$5 # return q; 27 0058 03E00008 00A01021 JR $31 28 .end udiv64 RISC-V GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър a0 частното, а на адрес, 2 # подаден в регистър a3, да записва остатъка от деленето на числото в регистри 3 # a1:a0 на числото в регистър a2. 4 5 .global udiv64 # http://codereview.stackexchange.com/questions/67962 6 udiv64: # q = a_lo<<1;(r = a_hi;)//няма нужда от отделни q, r 7 0000 9357F501 SRLI a5,a0,31# /carry = a_lo >> 31; 8 0004 0605 SLLI a0,a0,1 #_/ 9 0006 13070002 LI a4,32 #брч 10 000a 13D8F501 L1: SRLI a6,a1,31# temp = r >> 31; 11 000e 8605 SLLI a1,a1,1 # r = r << 1 12 0010 DD8D OR a1,a1,a5# | carry; 13 0012 C287 MV a5,a6 # carry = temp; 14 0014 81E7 BNEZ a5,L2 # if (carry == 0) { 15 0016 63E4C500 BLTU a1,a2,L3# if (r < b) goto shift; 16 001a 8507 ADDI a5,a5,1 # carry++; 17 001c 918D L2: SUB a1,a1,a2# } r -= b; 18 001e 1358F501 L3: SRLI a6,a0,31#shift: temp = q >> 31; 19 0022 0605 SLLI a0,a0,1 # q = q << 1 20 0024 5D8D OR a0,a0,a5# | carry; 21 0026 C287 MV a5,a6 # carry = temp; 22 0028 7D17 ADDI a4,a4,-1#Следваща 23 002a 65F3 BNEZ a4,L1 #итерация 24 002c 8CC2 SW a1,0(a3)# *rem = r; 25 002e 8280 RET # return q; Nios II GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 частното, а на адрес, 2 # подаден в регистър r7, да записва остатъка от деленето на числото в регистри 3 # r5:r4 на числото в регистър r6. 4 5 .global udiv64 # http://codereview.stackexchange.com/questions/67962 6 udiv64: # q = a_lo<<1;(r = a_hi;)//няма нужда от отделни q, r 7 0000 FAD71220 SRLI r9,r4,31# /carry = a_lo >> 31; 8 0004 7A900820 SLLI r4,r4,1 #_/ 9 0008 14080002 MOVUI r8,32 #брч 10 000c FAD70628 L1: SRLI r3,r5,31# temp = r >> 31; 11 0010 7A900A28 SLLI r5,r5,1 # r = r << 1 12 0014 3AB04A2A OR r5,r5,r9# | carry; 13 0018 3A881318 MOV r9,r3 # carry = temp; 14 001c 1E020048 BNE r9,r0,L2# if (carry == 0) { 15 0020 36028029 BLTU r5,r6,L3# if (r < b) goto shift; 16 0024 4400404A ADDI r9,r9,1 # carry++; 17 0028 3AC88B29 L2: SUB r5,r5,r6# } r -= b; 18 002c FAD70620 L3: SRLI r3,r4,31#shift: temp = q >> 31; 19 0030 7A900820 SLLI r4,r4,1 # q = q << 1 20 0034 3AB04822 OR r4,r4,r9# | carry; 21 0038 3A881318 MOV r9,r3 # carry = temp; 22 003c C4FF3F42 ADDI r8,r8,-1#Следваща 23 0040 1EF23F40 BNE r8,r0,L1#итерация 24 0044 15004039 STW r5,(r7) # *rem = r; 25 0048 3A880520 MOV r2,r4 # return q; 26 004c 3A2800F8 RET Xtensa GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър a2 частното, а на адрес, 2 # подаден в регистър a5, да записва остатъка от деленето на числото в регистри 3 # a3:a2 на числото в регистър a4. 4 5 .global udiv64 # http://codereview.stackexchange.com/questions/67962 6 udiv64: # q = a_lo<<1;(r = a_hi;)//няма нужда от отделни q, r 7 0000 207F05 EXTUI a7,a2,31,1#/carry = a_lo >> 31; 8 0003 F02211 SLLI a2,a2,1 #_/ 9 0006 62A020 MOVI a6,32 #брч 10 0009 768622 LOOP a6,L3 #цкл 11 000c 308F05 EXTUI a8,a3,31,1 # temp = r >> 31; 12 000f F03311 SLLI a3,a3,1 # r = r << 1 13 0012 703320 OR a3,a3,a7 # | carry; 14 0015 807820 MOV a7,a8 # carry = temp; 15 0018 565700 BNEZ a7,L1 # if (carry == 0) { 16 001b 473305 BLTU a3,a4,L2 # if (r < b) goto shift; 17 001e 72C701 ADDI a7,a7,1 # carry++; 18 0021 4033C0 L1: SUB a3,a3,a4 # } r -= b; 19 0024 208F05 L2: EXTUI a8,a2,31,1 #shift: temp = q >> 31; 20 0027 F02211 SLLI a2,a2,1 # q = q << 1 21 002a 702220 OR a2,a2,a7 # | carry; 22 002d 7D08 MOV a7,a8 # carry = temp; 23 002f 3905 L3: S32I a3,a5,0 # *rem = r; 24 0031 0DF0 RET # return q; 88K GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър r2 частното, а на адрес, 2 # подаден в регистър r5, да записва остатъка от деленето на числото в регистри 3 # r2:r3 на числото в регистър r4. 4 5 .global _udiv64 # http://codereview.stackexchange.com/questions/67962 6 0000 58E00021 _udiv64: 7 0004 F4006100 or r7,r0,33#Брояч 8 0008 C0000008 addu.co r0,r0,r0#C↓_q = a_lo << 1; carry = a_lo >> 31; 9 000c F4426302 br L3 #_/(r = a_hi;)// няма нужда от отделни q и r 10 0010 F4C06200 L1: addu.cio r2,r2,r2# temp = r >> 31; r = r<<1 | carry; carry = temp; 11 0014 E9A60004 addu.ci r6,r0,r0#C=? 12 0018 F4C27C04 bcnd ne0,r6,L2# if (!carry) { 13 001c D9460003 cmp r6,r2,r4# if (r < b) 14 0020 F4006507 bb1 lo,r6,L3#C=0 goto shift; 15 0024 F4426404 subu.co r0,r0,r7#C↑ 16 0028 F4636303 L2: subu r2,r2,r4#C=1 (carry++;) } r -= b; 17 002c 64E70001 L3: addu.cio r3,r3,r3#shift:temp = q>>31; q = q<<1 | carry; carry = temp; 18 0030 E9A7FFF7 subu r7,r7,1 19 0034 F4452400 bcnd ne0,r7,L1#Следваща итерация 20 0038 F4435800 st r2,r5,r0# *rem = r; 21 003c F400C001 or r2,r3,r0# return q; jmp r1 Or1k GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R11 частното, а на адрес, 2 # подаден в регистър R6, да записва остатъка от деленето на числото в регистри 3 # R3:R4 на числото в регистър R5. 4 5 .global udiv64 # http://codereview.stackexchange.com/questions/67962 6 udiv64: 7 0000 0000000B L.J L3#изп.се след L.ADDI q = a_lo << 1; carry = a_lo >> 63; 8 0004 9D000021 L.ADDI R8,R0,33#SR[CY] = 0 (r = a_hi;)//няма нужда от отделни q и r 9 0008 9CE7FFFF L1: L.ADDI R7,R7,-1 # Възстанови SR[CY] 10 000c E5830000 L.SFLTS R3,R0 # carry = SR[F] temp = r >> 63; r = 11 0010 E0631801 L.ADDC R3,R3,R3 # r << 1 | carry; carry = temp; 12 0014 10000004 L.BF L2#след L.SFLTU, но нищо! if (carry == 0) { 13 0018 E4832800 L.SFLTU R3,R5 # if (r < b) 14 001c 10000004 L.BF L3 # goto shift; 15 0020 15000000 L.NOP # carry++; 16 0024 E0632802 L2: L.SUB R3,R3,R5 # } r -= b; 17 0028 E0E04002 L.SUB R7,R0,R8 # Възстанови 1 в SR[CY] 18 002c E0842001 L3: L.ADDC R4,R4,R4 # shift: temp = q >> 63; q = 19 0030 E0E00001 L.ADDC R7,R0,R0 # Съхр. SR[CY] q << 1 | carry; carry = temp; 20 0034 9D08FFFF L.ADDI R8,R8,-1 # Обнови брояча 21 0038 E4280000 L.SFNE R8,R0 # Следваща итерация на цикъла? 22 003c 13FFFFF3 L.BF L1 # Да, продължи (изпълн. се след L.OR, но нищо!) 23 0040 E1640004 L.OR R11,R4,R0 # Не, край 24 0044 44004800 L.JR LR#след L.SW #__ __ *rem = r; 25 0048 D4061800 L.SW 0(R6),R3 #__X__ return q;//Върни q в R11 Xilinx MicroBlaze GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R3 частното, а на адрес, 2 # подаден в регистър R8, да записва остатъка от деленето на числото в регистри 3 # R6:R5 на числото в регистър R7. 4 5 .global udiv64 # http://codereview.stackexchange.com/questions/67962 6 udiv64: 7 0000 21006020 ADDI R3,R0,33#↓C_q = a_lo << 1; carry = a_lo >> 31; 8 0004 200000B8 BRI L3 #_/(r = a_hi;)// няма нужда от отделни q и r 9 0008 0030C608 L1: ADDC R6,R6,R6# temp = r >> 31; r = r<<1 | carry; carry = temp; 10 000c FFFF8028 ADDIC R4,R0,-1#C-1=? (запази C) 11 0010 100004BC BEQI R4,L2 # if (!carry) { 12 0014 03308714 CMPU R4,R7,R6# if (r < b) 13 0018 00300704 RSUB R0,R7,R6#обн.C 14 001c 080044BC BLTI R4,L3 # goto shift; 15 0020 0030C714 L2: RSUBK R6,R7,R6#C=1 (carry++;) } r -= b; 16 0024 0028A508 L3: ADDC R5,R5,R5#shift: temp = q>>31; q = q<<1 | carry; carry = temp; 17 0028 FFFF6330 ADDIK R3,R3,-1# Обнови брояча 18 002c DCFF23BC BNEI R3,L1 # Следваща итерация 19 0030 0000C8F8 SWI R6,R8,0 # *rem = r; 20 0034 08000FB6 RTSD R15,8 # return q; 21 0038 00006580 OR R3,R5,R0# Изпълнява се преди „RTSD“! HPPA GAS udiv64.s page 1 1 ; Да се напише подпрограма, която да връща в регистър %R28 частното, а на 2 ; адрес, подаден в регистър %R23, да записва остатъка от деленето на числото в 3 ; регистри %R25:%R26 на числото в регистър %R24. 4 5 .text 6 .global udiv64 ; http://codereview.stackexchange.com/questions/67962 7 udiv64: 8 0000 E8000030 B L3 ; q = a_lo << 1; carry = a_lo >> 31; (след „LDI“) 9 0004 34010042 LDI 33,%R1 ; Брч (r = a_hi;)//няма нужда от отделни q и r 10 0008 0B398719 L1: ADDC,NUV %R25,%R25,%R25;temp = r>>31; r = r<<1 | carry; carry = temp; 11 000c E800000A B,N L2 ; if(!carry) { 12 0010 0B38A880 COMCLR,<<= %R24,%R25,%R0; if (r < b) 13 0014 E800000A B,N L3 ; C = 0 goto shift; 14 0018 0B190419 L2: SUB %R25,%R24,%R25; C = 1 (carry++;) } r -= b; 15 001c 08000400 SUB %R0,%R0,%R0; Възстанови C 16 0020 AC3F3FC5 L3: ADDIBF,= -1,%R1,L1; Следваща итерация на цикъла (изпълн.се след „ADDC“) 17 0024 0B5A071A ADDC %R26,%R26,%R26; shift: temp=q>>31; q=q<<1|carry; carry=temp; 18 0028 0EF91280 STWS %R25,0(%R23); *rem = r; 19 002c E840C000 BV (%R2) ; return q; 20 0030 081A025C COPY %R26,%R28; Върни q в %R28 (изпълнява се преди „BV“!) 20 00000000 Renesas / SuperH SH GAS Little Endian udiv64.s page 1 1 ! Да се напише подпрограма, която да връща в регистър R0 частното, а на адрес, 2 ! подаден в регистър R7, да записва остатъка от деленето на числото в регистри 3 ! R5:R4 на числото в регистър R6. 4 5 .global udiv64 6 udiv64: 7 0000 0A45 LDS R5,MACH ! Подготви старшата 8 0002 1A44 LDS R4,MACL ! и младшата дума на делимото за „UDIV“ 9 0004 4365 MOV R4,R5 ! Съхрани младшата за изваждането със „SUB“ 10 0006 05D0 MOV.L UDIVPTR,R0 ! Адрес на „UDIV“ 11 0008 224F STS.L PR,@-SP ! Съхрани PR, защото „JSR“ ще го промени! 12 000a 0B40 JSR @R0 ! Върни частното в R0 13 000c 6364 MOV R6,R4 ! Делител за „UDIV“ (изпълнява се преди „JSR“!) 14 000e 264F LDS.L @SP+,PR ! Възстанови адреса на връщане 15 0010 4700 MUL.L R4,R0 ! Изчисли произведението на делителя и частното 16 0012 1A04 STS MACL,R4 17 0014 4835 SUB R4,R5 ! Получи остатъка (пренебрегвайки преноса) и го 18 0016 0B00 RTS 19 0018 5227 MOV.L R5,@R7 ! запиши на искания адрес (изп.се преди „RTS“!) 20 001a 0900 .align 2 21 001c 00000000 UDIVPTR:.long UDIV UNDEFINED SYMBOLS UDIV GAS for CRIS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R10 частното, а на адрес, 2 # подаден в регистър R13, да записва остатъка от деленето на числото в регистри 3 # R11:R10 на числото в регистър R12. 4 5 .global udiv64 ; http://codereview.stackexchange.com/questions/67962 6 udiv64: 7 0000 F105 CLEARF C 8 0002 16E0 BA L3;изп.се след MOVU q = a_lo << 1; carry = a_lo >> 63; 9 0004 4F9C2100 MOVU.B 33,$R9 ; (r = a_hi;)//няма нужда от отделни q и r 10 0008 3FD6 L1: MOVE $R15,$CCS ; Възстанови C temp = r >> 63; r = 11 000a 7BB5 ADDC $R11,$R11 ; r << 1 | carry; carry = temp; 12 000c 0810 BCS L2;след CMP, но нищо! if (carry == 0) { 13 000e EBC6 CMP.D $R11,$R12 ; if (r < b) 14 0010 0890 BHI L3 ; C || Z = 0 goto shift; 15 0012 B005 NOP ; C || Z = 1 ___ carry++; 16 0014 ACB6 L2: SUB.D $R12,$R11 ; / } r -= b; 17 0016 B105 SETF C ;__________/ 18 0018 7AA5 L3: ADDC $R10,$R10 ; shift: temp = q >> 63; q = 19 001a 7FD6 MOVE $CCS,$R15 ; Съхрани C q << 1 | carry; carry = temp; 20 001c 8192 SUBQ 1,$R9 ; Следваща итерация на цикъла? 21 001e EB20 BNE L1 ; Да, продължи 22 0020 B005 NOP ; Не, край 23 0022 F0B9 RET ;след MOVE ;__ __ *rem = r; 24 0024 EDBB0000 MOVE.D $R11,[$R13] ;__X__ return q;//Върни q в R10 BFIN GAS udiv64.s page 1 1 # Да се напише подпрограма, която да връща в регистър R0 частното, а на адрес, 2 # подаден в [SP+12], да записва остатъка от деленето на числото в регистри 3 # R1:R0 на числото в регистър R2. 4 5 .global _udiv64 # http://codereview.stackexchange.com/questions/67962 6 _udiv64: # q = a_lo << 1;(r = a_hi;)//няма нужда от отделни q, r 7 0000 9208 CC = R2 < R2; # carry/= a_lo >> 31; 8 0002 82C608C0 R0 = ROT R0 BY 1;#____/____/ 9 0006 0069 P0 = 32; #итерации 10 0008 A2E00800 LSETUP (L_1, L_3) LC0 = P0; 11 000c 82C609C2 L_1: R1 = ROT R1 BY 1; # temp = r >> 31; r = r << 1 | carry; carry = temp; 12 0010 0318 IF CC JUMP L_2; # if (carry == 0) { 13 0012 0A0A CC = R2 <= R1 (IU);# if (r < b) 14 0014 0210 IF !CC JUMP L_3; # goto shift; (carry++;)// CC вече е лог. 1 15 0016 5152 L_2: R1 = R1 - R2; # } r -= b; 16 0018 82C608C0 L_3: R0 = ROT R0 BY 1;#shift:temp=q >> 31; q = q << 1 | carry; carry = temp; 17 001c F0AC P0 = [SP + 12]; # 18 001e 0193 [P0] = R1; # *rem = r; 19 0020 10000000 RTS; # return q; Hexagon GAS udiv64.s page 1 1 // Да се напише подпрограма, която да връща в регистър R0 частното, а на адрес, 2 // подаден в регистър R3, ако той е ненулев, да записва остатъка от деленето на 3 // числото в регистри R1:R0 на числото в регистър R2. 4 5 .global udiv64 // http://codereview.stackexchange.com/questions/67962 6 udiv64: // q = a_lo<<1;(r = a_hi;)//няма нужда от отделни q, r 7 0000 24DF008C R4 = LSR(R0,#31)//carry= a_lo >> 31; 8 { R0 = ASL(R0,#1)//q 9 0004 10400169 40C1008C LOOP0 (L1,#32) }//брч 10 000c 25DF018C L1: R5 = LSR(R1,#31)// temp = r >> 31; 11 { R1 = ADDASL(R4,R1,#1)//r = r << 1 | carry; 12 0010 214401C4 04C06570 R4 = R5 } // carry = temp; 13 { P0 = CMP.GT(R0,R0)//P0=0 14 0018 08500461 00C040F2 IF (R4!=#0) JUMP:T L2 }//if (carry == 0) { 15 { P0 = CMP.LTU(R1,R2)// if (r < b) goto shift; 16 0020 004162F2 24E0807E IF (!P0.NEW) R4 = #1 }// carry++; 17 L2: { IF (!P0) R1 = SUB(R1,R2)//} r -= b; 18 0028 814122FB 25DF008C R5 = LSR(R0,#31) }//shift:temp = q >> 31; 19 { R0 = ADDASL(R4,R0,#1)//q = q << 1 | carry; 20 0030 208400C4 04C06570 R4 = R5 }:ENDLOOP0//carry = temp; 21 { P0 = CMP.EQ(R3,#0)// Нулев адрес? Прескочи записа 22 IF (!P0.NEW) MEMW(R3) = R1//*rem = r; 23 0038 00400375 00409F52 00C18346 JUMPR LR } // return q; S/390 GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри 2:3 частното, а на 2 # адрес, подаден в SP(104), да записва 64-битовия остатък от деленето на 3 # числото в регистри 4:5:2:3 на числото в SP(96):SP(100). 4 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 9068F008 STM 6,8,8(15) # Съхрани използваните регистри (LNUX-1007-02) 8 0004 9868F060 LM 6,8,96(15) # b = 6:7, rem = 8 9 0008 1700 XR 0,0 # CC=0 10 000a A7180041 LHI 1,65 # q = a_lo << 1; carry = a_lo >> 63; 11 000e A7F40015 J L3 # (r = a_hi;)//няма нужда от отделни q и r 12 0012 B9980055 L1: ALCR 5,5 # temp = r >> 63; r = 13 0016 B9980044 ALCR 4,4 # r << 1 | carry; carry = temp; 14 001a A734000A BRC 3,L2 # CC=2|3 if (carry == 0) { 15 001e 1546 CLR 4,6 # if (r < b) 16 0020 A744000C JL L3 # CC=1 goto shift; 17 0024 A7240005 JH L2 # CC=2 carry++; 18 0028 1557 CLR 5,7 # Старшите думи са равни – сравни младшите 19 002a A7440007 JL L3 # CC=1 20 002e 1F57 L2: SLR 5,7 # } 21 0030 B9990046 SLBR 4,6 # r -= b; 22 0034 A71E0000 CHI 1,0 # Възстанови CC=2 23 0038 B9980033 L3: ALCR 3,3 # shift: temp = q >> 63; q = 24 003c B9980022 ALCR 2,2 # q << 1 | carry; carry = temp; 25 0040 A716FFE9 BRCT 1,L1 # Следваща итерация на цикъла 26 0044 90458000 STM 4,5,0(8) # *rem = r; 27 0048 9868F008 LM 6,8,8(15) # return q;//Възст. и върни q в рег. 2:3 28 004c 07FE0707 BR 14 ==> id32/udiv128.s <== 1 * Write at the address passed in 7(24) the quotient and at the 2 * address passed in 7(28) - the remainder of the division of the number in 3 * 7(8):7(12):7(0):7(4) -> reg.2:3:0:1 to the number in 7(16):7(20) -> reg.4:5. 4 5 * ID32 lacks addition/subtraction with carry, so we use the CPU's C flag only 6 * between high and low words of 64-bit operations, not for the "carry" variable 7 8 entry udiv128 http://codereview.stackexchange.com/questions/67962 00000000d 9 udiv128 equ * 00000d 5807 0000 10 l 0,0(7) Registers: 00004d 5817 0004 11 l 1,4(7) 0:1 = a_lo 00008d 5827 0008 12 l 2,8(7) 2:3 = a_hi 0000Cd 5837 000C 13 l 3,12(7) (a_hi:a_lo = a = 128-bit dividend) 00010d 5847 0010 14 l 4,16(7) 4:5 = b = 64-bit divisor 00014d 5857 0014 15 l 5,20(7) 6 = temp, 8 = carry, 9 = counter 00018d CB70 0020 16 shi 7,32(0) Allocate stack space (8 * 4 bytes = 32 bytes) 0001Cd D087 0000 17 stm 8,0(7) Save reg. 8-15 (used by the calling function) 00020d 0788 18 xr 8,8 00022d C890 0041 19 lhi 9,65(0) _q = a_lo << 1; carry = a_lo >> 63; 00026d 4300 8028 00000052d 20 b L6(0) __/(r = a_hi;)// no need of separate q and r 0002Ad 0862 21 L1 lr 6,2 temp = r 0002Cd EC60 001F 22 srl 6,31(0) >> 63; 00030d 1121 23 slls 2,1 r = r<<1 00032d 1131 24 slls 3,1 00034d 2382 00000038d 25 bncs L2 00036d 2621 26 ais 2,1 00038d 0638 27 L2 or 3,8 | carry; 0003Ad 0886 28 lr 8,6 carry = temp; 0003Cd 2137 0000004Ad 29 bnzs L4 if (!carry) { 0003Ed 0524 30 clr 2,4 if (r < b) 00040d 2189 00000052d 31 bls L6 00042d 2133 00000048d 32 bnzs L3 No BHS 00044d 0535 33 clr 3,5 00046d 2186 00000052d 34 bls L6 goto shift; 00048d 2481 35 L3 lis 8,1 carry++; // carry = 1 as lowest bit matters 0004Ad 0B35 36 L4 sr 3,5 } 0004Cd 2382 00000050d 37 bncs L5 r -= b; 0004Ed 2721 38 sis 2,1 00050d 0B24 39 L5 sr 2,4 00052d 0860 40 L6 lr 6,0 shift:temp = q 00054d EC60 001F 41 srl 6,31(0) >>63; 00058d 1101 42 slls 0,1 q = q<<1 0005Ad 1111 43 slls 1,1 0005Cd 2382 00000060d 44 bncs L7 0005Ed 2601 45 ais 0,1 00060d 0618 46 L7 or 1,8 | carry; 00062d 0886 47 lr 8,6 carry = temp; 00064d 2791 48 sis 9,1 Next iteration 00066d 4230 FFC0 0000002Ad 49 bnz L1(0) 0006Ad D187 0000 50 lm 8,0(7) Restore the saved registers 8-15 0006Ed CA70 0020 51 ahi 7,32(0) Deallocate the stack space 00072d 5867 0018 52 l 6,24(7) Quotient address 00076d 5006 0000 53 st 0,0(6) Write the quotient 0007Ad 5016 0004 54 st 1,4(6) 0007Ed 5867 001C 55 l 6,28(7) *rem 00082d 5026 0000 56 st 2,0(6) = r; 00086d 5036 0004 57 st 3,4(6) 0008Ad 030F 58 br 15 // return q; VAX GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри R1:R0 частното, а на 2 # адрес, подаден в AP(28), да записва 64-битовия остатък от деленето на числото 3 # в AP(16):AP(12):AP(8):AP(4) -> R3:R2:R1:R0 на числото в AP(24):AP(20). 4 5 .global _udiv128 # http://codereview.stackexchange.com/questions/67962 6 _udiv128: 7 0000 1C00 .word 0x1C # R2-R4; командата CALLS вече е нулирала флаг C 8 0002 FD7DAC04 50 MOVO 4(AP),R0 # R3:R2:R1:R0 = делимо 9 0007 D08F4100 000054 MOVL $65,R4 # Брч __q = a_lo << 1; carry = a_lo >> 63; 10 000e 1120 BRB L3 # ___/ (r = a_hi;)//няма нужда от отделни q и r 11 0010 D85252 L1: ADWC R2,R2 # temp = r >> 63; r = 12 0013 D85353 ADWC R3,R3 # r << 1 | carry; carry = temp; 13 0016 1F0E BCS L2 # if (carry == 0) { 14 0018 D1AC1853 CMPL 24(AP),R3 # if (r < b) 15 001c 1A12 BGTRU L3 # C = 0 goto shift; 16 001e 1F06 BLSSU L2 # C = 1 carry++; 17 0020 D1AC1452 CMPL 20(AP),R2 # Старшите думи са равни – сравни младшите 18 0024 1A0A BGTRU L3 # C = 0 19 0026 C2AC1452 L2: SUBL2 20(AP),R2 # } 20 002a D9AC1853 SBWC 24(AP),R3 # r -= b; 21 002e B801 BISPSW $1 # Възстанови C 22 0030 D85050 L3: ADWC R0,R0 # shift: temp = q >> 63; q = 23 0033 D85151 ADWC R1,R1 # q << 1 | carry; carry = temp; 24 0036 F554D7 SOBGTR R4,L1 # Следваща итерация на цикъла 25 0039 7D52BC1C MOVQ R2,*28(AP) # *rem = r; 26 003d 040101 RET # return q;//Възстанови и върни q в R1:R0 ==> we32k/udiv128.s <== # Return in registers r0:r1 the quotient, and write at the address # passed in ap(24) the remainder of the division of the number in # ap(8):ap(12):ap(0):ap(4) -> r2:r3:r0:r1 to the number in # ap(16):ap(20) -> r4:r5. # WE32K lacks addition/subtraction with carry, so we use the CPU's C flag only # between the high and low words in subtraction, and not for shift operations. section .text .globl udiv128 # http://codereview.stackexchange.com/questions/67962 udiv128() udiv128: 0: 10 43 SAVE %r3 #"AT&T 382/385/3815 Computers Assembly Language 2: 84 5a 40 MOVW 0(%ap),%r0 # Programming Manual", pp. 6-13, 6-14 5: 84 74 41 MOVW 4(%ap),%r1 # r0:r1 = a_lo 8: 84 78 42 MOVW 8(%ap),%r2 # r2:r3 = a_hi b: 84 7c 43 MOVW 12(%ap),%r3 # (a_hi:a_lo = a = 128-bit dividend) e: 84 ca 10 44 MOVW 16(%ap),%r4 # r4:r5 = b = 64-bit divisor 12: 84 ca 14 45 MOVW 20(%ap),%r5 # r6 = temp, r7 = carry, r8 = counter 16: 70 NOP 17: 80 47 CLRW %r7 19: 84 6f 41 48 MOVW &65,%r8 # _q = a_lo << 1; carry = a_lo >> 63; 1d: 7b 39 BRB L5 #_/(r = a_hi;)// no need of separate q and r 1f: d4 1f 42 46 L1: LRSW3 &31,%r2,%r6# temp = r >> 63; 23: d0 01 42 42 LLSW3 &1,%r2,%r2# r = r<<1 27: d8 1f 43 43 ROTW &31,%r3,%r3 2b: c8 00 00 43 42 INSFW &0,&0,%r3,%r2 30: c8 00 00 47 43 INSFW &0,&0,%r7,%r3# | carry; 35: 70 NOP 36: 84 46 47 MOVW %r6,%r7 # carry = temp; 39: 28 47 TSTW %r7 3b: 77 11 BNEB L3 # if (!carry) { 3d: 3c 44 42 CMPW %r4,%r2 # if (r < b) 40: 57 09 BGUB L2 42: 5b 14 BLUB L5 44: 3c 45 43 CMPW %r5,%r3 47: 5b 0f BLUB L5 # goto shift; 49: 84 01 47 L2: MOVW &1,%r7 # carry++; // carry = 1 as lowest bit matters 4c: bc 45 43 L3: SUBW2 %r5,%r3 # } 4f: 53 04 BCCB L4 # r -= b; 51: 94 42 DECW %r2 53: bc 44 42 L4: SUBW2 %r4,%r2 56: d4 1f 40 46 L5: LRSW3 &31,%r0,%r6#shift:temp = q>>63; 5a: d0 01 40 40 LLSW3 &1,%r0,%r0# q = q<<1 5e: d8 1f 41 41 ROTW &31,%r1,%r1 62: c8 00 00 41 40 INSFW &0,&0,%r1,%r0 67: c8 00 00 47 41 INSFW &0,&0,%r7,%r1# | carry; 6c: 70 NOP 6d: 84 46 47 MOVW %r6,%r7 # carry = temp; 70: 97 48 DECB %r8 #Next iteration 72: 77 ad BNEB L1 74: 84 ca 18 46 MOVW 24(%ap),%r6#rem (deferred/indirect mode impossible for 64 bits) 78: 84 42 56 MOVW %r2,(%r6)# *rem = r; 7b: 70 NOP 7c: 84 43 c6 04 MOVW %r3,4(%r6) 80: 70 NOP 81: 04 59 4c MOVAW (%fp),%sp RESTORE %r3 84: 20 48 POPW %r8 86: 20 47 POPW %r7 88: 20 46 POPW %r6 8a: 20 45 POPW %r5 8c: 20 44 POPW %r4 8e: 20 43 POPW %r3 90: 20 49 POPW %fp 92: 08 RET # return q; 93: 70 NOP 68K GAS udiv128.s page 1 1 | Да се напише подпрограма, която да връща в регистри D0:D1 частното, а на 2 | адрес, подаден в SP(28), да записва 64-битовия остатък от деленето на числото 3 | в SP(12):SP(16):SP(4):SP(8) -> D2:D3:D0:D1 на това в SP(20):SP(24) -> D4:D5. 4 5 .global udiv128 | http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 4E56 0000 LINK %FP,#0 | Създай стекова рамка 8 0004 48E7 3E00 MOVEML %D2-%D6,-(%SP) | GCC изисква D2 и следващите да се съхраняват 9 0008 4CEE 013F 0008 MOVEML 8(%FP),%D0-%D5/%A0|Делимо: D2:D3:D0:D1, делител: D4:D5, rem: A0 10 000e 7C40 MOVEL #64,%D6 | 65 итерации − 1 („DBF“ спира цикъла при −1) 11 0010 023C 00EF ANDI #0xEF,%CCR | X=0 __q = a_lo << 1; carry = a_lo >> 63; 12 0014 6018 BRAB L3 | ___/ (r = a_hi;)//няма нужда от отделни q и r 13 0016 D783 L1: ADDXL %D3,%D3 | temp = r >> 63; r = 14 0018 D582 ADDXL %D2,%D2 | r << 1 | carry; carry = temp; 15 001a 650A BCSB L2 | X = 1 if (carry == 0) { 16 001c B484 CMPL %D4,%D2 | if (r < b) 17 001e 650E BLOB L3 | X = 0 goto shift; 18 0020 6204 BHIB L2 | X = 0 _______ carry++; 19 0022 B685 CMPL %D5,%D3 | Старшите думи/са равни – сравни младшите 20 0024 6508 BLOB L3 | X = 0 / } 21 0026 9685 L2: SUBL %D5,%D3 | / r -= b; 22 0028 9584 SUBXL %D4,%D2 | / 23 002a 003C 0010 ORI #0x10,%CCR | X = 1 ___/ 24 002e D381 L3: ADDXL %D1,%D1 | shift: temp = q >> 63; q = 25 0030 D180 ADDXL %D0,%D0 | q << 1 | carry; carry = temp; 26 0032 51CE FFE2 DBF %D6,L1 | Следваща итерация на цикъла 27 0036 48D0 000C MOVEML %D2-%D3,(%A0) | *rem = r; 28 003a 4CDF 007C MOVEML (%SP)+,%D2-%D6 | return q;//Възстанови и върни q в D0:D1 29 003e 4E5E UNLK %FP 30 0040 4E75 RTS x86 NASM udiv128.s 1 ; Да се напише подпрограма, която да връща в регистри EDX:EAX частното, а на 2 ; адрес, подаден в [ESP+28], да записва 64-битовия остатък от деленето на 3 ; числото в [ESP+16]:[ESP+12]:[ESP+8]:[ESP+4] на числото в [ESP+24]:[ESP+20]. 4 5 section .text 6 global udiv128,_udiv128 7 udiv128: 8 _udiv128: 9 00000000 8B442404 MOV EAX,[ESP+4];http://codereview.stackexchange.com/questions/67962 10 00000004 8B542408 MOV EDX,[ESP+8] ;// q = EDX:EAX (a_lo) 11 00000008 8774240C XCHG ESI,[ESP+12] ;// няма нужда от отделни q и r 12 0000000C 877C2410 XCHG EDI,[ESP+16] ;// r = EDI:ESI (a_hi), съхрани ESI и EDI 13 00000010 31C9 XOR ECX,ECX ;// CF = ECX = 0 14 00000012 B141 MOV CL,65 ;// LOOP изисква броячът да бъде в регистър ECX 15 00000014 EB1D JMP SHORT L3 ; q = a_lo << 1; carry = a_lo >> 63; 16 00000016 D1D6 L1: RCL ESI,1 ; temp = r >> 63; r = 17 00000018 D1D7 RCL EDI,1 ; r << 1 | carry; carry = temp; 18 0000001A 720E JC L2 ; if (carry == 0) { 19 0000001C 397C2418 CMP [ESP+24],EDI ; if (r < b) 20 00000020 7711 JA L3 ; goto shift; 21 00000022 7206 JB L2 ;// CF = 1 carry++; 22 00000024 39742414 CMP [ESP+20],ESI ;// Старшите думи са равни – сравни младшите 23 00000028 7709 JA L3 24 0000002A 2B742414 L2: SUB ESI,[ESP+20] ; } 25 0000002E 1B7C2418 SBB EDI,[ESP+24] ; r -= b; 26 00000032 F9 STC ;// Възстанови CF 27 00000033 D1D0 L3: RCL EAX,1 ; shift: temp = q >> 63; q = 28 00000035 D1D2 RCL EDX,1 ; q << 1 | carry; carry = temp; 29 00000037 E2DD LOOP L1 ;// Повтори 64 пъти 30 00000039 8B4C241C MOV ECX,[ESP+28] 31 0000003D 8931 MOV [ECX],ESI ; *rem = r; 32 0000003F 897904 MOV [ECX+4],EDI 33 00000042 8B74240C MOV ESI,[ESP+12] ;// Възстанови съхранените регистри 34 00000046 8B7C2410 MOV EDI,[ESP+16] 35 0000004A C3 RET ; return q; ARM GAS udiv128.s page 1 1 // Да се напише подпрограма, която да връща в регистри R1:R0 частното, а на 2 // адрес, подаден в [SP+8], да записва 64-битовия остатък от деленето на 3 // числото в регистри R3:R2:R1:R0 на числото в [SP+4]:[SP]. 4 5 .global udiv128 // http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 F0410DE9 STMDB SP,{R4-R8,LR} //Съхрани използваните регистри: ARM IHI 0042F 8 0004 C0019DE8 LDMIA SP,{R6-R8} // b = R7:R6, rem = R8 9 0008 4140A0E3 MOV R4,#65 //Брч _q = a_lo << 1; carry = a_lo >> 63; 10 000c 28F09FE2 ADDS PC,PC,#L3-(.+8) //C=0_/(r = a_hi;)//няма нужда от отделни q и r 11 0010 05F028E1 L1: MSR CPSR_f,R5 // Възстанови C 12 0014 0220B2E0 ADCS R2,R2,R2 // temp = r >> 63; r = 13 0018 0330B3E0 ADCS R3,R3,R3 // r << 1 | carry; carry = temp; 14 001c 0300002A BCS L2 // if (carry == 0) { 15 0020 070053E1 CMP R3,R7 // if (r < b) 16 0024 0400003A BLO L3 // C = 0 goto shift; 17 0028 06005201 CMPEQ R2,R6 // Старшите думи са равни – сравни младшите 18 002c 0200003A BLO L3 // C = 0 __________ carry++; 19 0030 062052E0 L2: SUBS R2,R2,R6 // C = 1 / } 20 0034 0730C3E0 SBC R3,R3,R7 // / r -= b; 21 0038 050055E1 CMP R5,R5 //________/ 22 003c 0000B0E0 L3: ADCS R0,R0,R0 // shift: temp = q >> 63; q = 23 0040 0110B1E0 ADCS R1,R1,R1 // q << 1 | carry; carry = temp; 24 0044 00500FE1 MRS R5,CPSR // Съхрани C 25 0048 014054E2 SUBS R4,R4,#1 // Следваща итерация на цикъла? 26 004c EFFFFF1A BNE L1 // Да, продължи 27 0050 0C0088E8 STMIA R8,{R2,R3} // *rem = r; 28 0054 F0811DE9 LDMDB SP,{R4-R8,PC} // return q;//Възстанови и върни q в R1:R0 ARC GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри r1:r0 частното, а на 2 # адрес, подаден в регистър r6, да записва 64-битовия остатък от деленето на 3 # числото в регистри r3:r2:r1:r0 на числото в r5:r4. 4 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 8A24 0170 MOV lp_count,64 # Брч b = r5:r4, rem = r6 8 0004 2F20 0080 ASL.F r0,r0 # __q = a_lo << 1; carry = a_lo >> 63; 9 0008 2F21 4B80 RLC.F r1,r1 #___/ (r = a_hi;)//няма нужда от отделни q и r 10 000c A820 C005 LP L4 # Задай начало и край на цикъла 11 0010 2F22 8B80 RLC.F r2,r2 # Нач на цик. temp = r >> 63; r = 12 0014 2F23 CB80 RLC.F r3,r3 # r << 1 | carry; carry = temp; 13 0018 87F7 BLO_S L2 # if (carry == 0) { 14 001a 1B0B 4401 BRLO r3,r5,L3 # if (r < b) goto shift; 15 001e 0B0D C400 BRHI r3,r5,L2 # ____________ carry++; 16 0022 130A 0401 BRLO r2,r4,L3 # Старшите/думи са равни – сравни младшите 17 0026 0222 0281 L2: SUB.F r2,r2,r4 # / } 18 002a 0323 4301 SBC r3,r3,r5 # / r -= b; 19 002e 4E26 3E80 RSUB.F 0,r6,0 #______/ 20 0032 2F20 0B80 L3: RLC.F r0,r0 # shift: temp = q >> 63; q = 21 0036 2F21 4B80 RLC.F r1,r1 # Край на цик. q << 1 | carry; carry = temp; 22 003a 001E 8600 L4: STD r2,[r6] #_/ *rem = r; 23 003e E07E J_S [blink] # return q;//Върни q в r1:r0 PPC GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри r3:r4 частното, а на 2 # адрес, подаден в r9, да записва 64-битовия остатък от деленето на числото 3 # в регистри r5:r6:r3:r4 на числото в r7:r8. 4 # 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 38000000 li r0,0 # Ще потрябва за проверка на преноса 8 0004 35400041 addic. r10,r0,65#CA=0, 65 итерации 9 0008 7D4903A6 mtctr r10 # ___ q = a_lo << 1; carry = a_lo >> 63; 10 000c 4800003C b L3 #__/ (r = a_hi;)// няма нужда от отделни q и r 11 0010 7CC63114 L1: adde r6,r6,r6# temp = r >> 63; 12 0014 7CA52914 adde r5,r5,r5# r = r << 1 | carry; carry = temp; 13 0018 7D4001D5 addme. r10,r0 #CA-1=? (запази CA) 14 001c 41820020 beq L2 # if (carry == 0) { 15 0020 7C053840 cmplw r5,r7 # if (r < b) 16 0024 7D472810 subfc r10,r7,r5#обн.CA 17 0028 41800020 blt L3 # goto shift; 18 002c 41810010 bgt L2 19 0030 7C064040 cmplw r6,r8 # Старшите думи са равни – сравни младшите 20 0034 7D483010 subfc r10,r8,r6#обн.CA 21 0038 41800010 blt L3 #CA=0 ____ carry++; 22 003c 7CC83010 L2: subfc r6,r8,r6#CA=1 / } 23 0040 7CA72910 subfe r5,r7,r5# / r -= b; 24 0044 7C000010 subfc r0,r0,r0#___/ 25 0048 7C842114 L3: adde r4,r4,r4#shift: temp = q >> 63; 26 004c 7C631914 adde r3,r3,r3# q = q << 1 | carry; carry = temp; 27 0050 4200FFC0 bdnz L1 # Следваща итерация 28 0054 90A90000 stw r5,0(r9)# *rem = r; 29 0058 90C90004 stw r6,4(r9) 30 005c 4E800020 blr # return q;// Върни q в r3:r4 SPARC GAS udiv128.s page 1 1 ! Да се напише подпрограма, която да връща в регистри %o0:%o1 частното, а на 2 ! адрес, подаден в [%sp+92], да записва 64-битовия остатък от деленето на 3 ! числото в регистри %o2:%o3:%o0:o%1 на числото в %o4:%o5. 4 5 .global udiv128 ! http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 9DE3BFA0 save %sp,-96,%sp !davidlitchfield.com/sparc_buffer_overflows.pdf 8 0004 E007A05C ld [%fp+92],%l0 ! rem = %l0 (b = %i4:%i5) 9 0008 10800010 ba L3!изпълн.се след orcc q = a_lo << 1; carry = a_lo >> 63; 10 000c A2902041 orcc %g0,65,%l1 !C=0 (r = a_hi;)//няма нужда от отделни q и r 11 0010 8084A001 L1: addcc %l2,1,%g0 ! Възстанови C 12 0014 B6C6C01B addxcc %i3,%i3,%i3 ! temp = r >> 63; r = 13 0018 B4C6801A addxcc %i2,%i2,%i2 ! r << 1 | carry; carry = temp; 14 001c 0A800008 bcs L2!след cmp, но нищо! if (carry == 0) { 15 0020 80A7001A cmp %i4,%i2 ! if (r < b) 16 0024 18800009 bgu L3 ! goto shift; 17 0028 01000000 nop 18 002c 0A800004 bcs L2!след cmp, но нищо! C = 1 carry++; 19 0030 80A7401B cmp %i5,%i3 ! Старшите думи са равни – сравни младшите 20 0034 18800005 bgu L3 21 0038 01000000 nop 22 003c B6A6C01D L2: subcc %i3,%i5,%i3 ! } 23 0040 B466801C subx %i2,%i4,%i2 ! r -= b; 24 0044 80A02001 subcc %g0,1,%g0 ! Възстанови 1 в C 25 0048 B2C64019 L3: addxcc %i1,%i1,%i1 ! shift: temp = q >> 63; q = 26 004c B0C60018 addxcc %i0,%i0,%i0 ! q << 1 | carry; carry = temp; 27 0050 A4600000 subx %g0,%g0,%l2 ! Съхрани C 28 0054 A2A46001 subcc %l1,1,%l1 ! Следваща итерация на цикъла? 29 0058 12BFFFEE bne L1 ! Да, продължи 30 005c 01000000 nop 31 0060 F4240000 st %i2,[%l0] 32 0064 F6242004 st %i3,[%l0+4] ! *rem = r; 33 0068 81C7E008 ret ! return q;//Възст. и върни q в %o0:%o1 34 006c 81E80000 restore MIPS GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри $2:$3 частното, а на 2 # адрес, подаден в [$29+24], да записва 64-битовия остатък от деленето на 3 # числото в регистри $6:$7:$4:$5 на числото в [$29+16]:[$29+20]. 4 5 .ent udiv128 # http://codereview.stackexchange.com/questions/67962 6 .global udiv128 7 udiv128: 8 0000 8FA80010 LW $8,16($29) 9 0004 8FA90014 LW $9,20($29) #b = $8:$9 10 0008 8FAA0018 LW $10,24($29) #rem 11 000c 00005821 MOVE $11,$0 #carry 12 LI $2,65 # брояч _q = a_lo << 1; carry = a_lo >> 63; 13 0010 10000017 24020041 B L4 #_/(r = a_hi;)// няма нужда от отделни q и r 14 0018 000667C2 L1: SRL $12,$6,31 # temp = r >> 63; 15 001c 00063040 SLL $6,$6,1 16 0020 00273FC2 ROTR $7,$7,31 17 0024 7CE60004 INS $6,$7,0,1 # r = r << 1 18 0028 7D670004 INS $7,$11,0,1 # | carry; 19 002c 01805821 MOVE $11,$12 # carry = temp; 20 0030 1560000B 00000000 BNE $11,$0,L3 # if (carry == 0) { 21 0038 00C8082B 1420000C 00000000 BLTU $6,$8,L4 # if (r < b) 22 0044 0106082B 14200004 00000000 BGTU $6,$8,L2 # goto shift; 23 0050 00E9082B 14200006 00000000 BLTU $7,$9,L4# Старшите думи са равни – сравни младшите 24 005c 256B0001 L2: ADDIU $11,$11,1 # carry++; 25 0060 00E9182B L3: SLTU $3,$7,$9# заем } 26 0064 00E93823 SUBU $7,$7,$9 27 0068 00C83023 SUBU $6,$6,$8 28 006c 00C33023 SUBU $6,$6,$3 # r -= b; 29 0070 000467C2 L4: SRL $12,$4,31 #shift: temp = q >> 63; 30 0074 00042040 SLL $4,$4,1 31 0078 00252FC2 ROTR $5,$5,31 32 007c 7CA40004 INS $4,$5,0,1 # q = q << 1 33 0080 7D650004 INS $5,$11,0,1 # | carry; 34 0084 01805821 MOVE $11,$12 # carry = temp; 35 0088 2442FFFF ADDIU $2,$2,-1# Следваща 36 008c 1440FFE2 00000000 BNE $2,$0,L1# итерация 37 0094 AD460000 SW $6,0($10) 38 0098 AD470004 SW $7,4($10) # *rem = r; 39 009c 00A01821 MOVE $3,$5 40 MOVE $2,$4 41 00a0 03E00008 00801021 JR $31 # return q;// Върни q в $2:$3 42 00a8 00000000 00000000 .end udiv128 RISC-V GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри a1:a0 частното, а на 2 # адрес, подаден в регистър a6, да записва 64-битовия остатък от деленето на 3 # числото в регистри a3:a2:a1:a0 на числото в регистри a5:a4. 4 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 93080000 MV a7,x0 #carry 8 0004 13031004 LI t1,65 # брояч _q = a_lo << 1; carry = a_lo >> 63; 9 0008 1DA8 J L4 #_/(r = a_hi;)// няма нужда от отделни q и r 10 000a 93D2F601 L1: SRLI t0,a3,31 # temp = r >> 63; 11 000e 8606 SLLI a3,a3,1 12 0010 9353F601 SRLI t2,a2,31 13 0014 B3E67600 OR a3,a3,t2 14 0018 0606 SLLI a2,a2,1 # r = r << 1 15 001a 33661601 OR a2,a2,a7 # | carry; 16 001e 9688 MV a7,t0 # carry = temp; 17 0020 63990800 BNEZ a7,L3 # if (carry == 0) { 18 0024 63EDF600 BLTU a3,a5,L4 # if (r < b) 19 0028 63E4D700 BGTU a3,a5,L2 # goto shift; 20 002c 6369E600 BLTU a2,a4,L4# Старшите думи са равни – сравни младшите 21 0030 8508 L2: ADDI a7,a7,1 # carry++; 22 0032 B333E600 L3: SLTU t2,a2,a4# заем } 23 0036 198E SUB a2,a2,a4 24 0038 9D8E SUB a3,a3,a5 25 003a B3867640 SUB a3,a3,t2 # r -= b; 26 003e 93D2F501 L4: SRLI t0,a1,31 #shift: temp = q >> 63; 27 0042 8605 SLLI a1,a1,1 28 0044 9353F501 SRLI t2,a0,31 29 0048 B3E57500 OR a1,a1,t2 30 004c 0605 SLLI a0,a0,1 # q = q << 1 31 004e 33651501 OR a0,a0,a7 # | carry; 32 0052 9688 MV a7,t0 # carry = temp; 33 0054 7D13 ADDI t1,t1,-1# Следваща 34 0056 E31A03FA BNEZ t1,L1 # итерация 35 005a 2320C800 SW a2,0(a6) 36 005e 2322D800 SW a3,4(a6) # *rem = r; 37 0062 8280 RET # return q;// Върни q в a1:a0 Nios II GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри r3:r2 частното, а на 2 # адрес, подаден в [sp+8], да записва 64-битовия остатък от деленето на 3 # числото в регистри r7:r6:r5:r4 на числото в регистри [sp+4]:[sp]. 4 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 170000DA LDW r8,(sp) 8 0004 170140DA LDW r9,4(sp) #b = r9:r8 9 0008 170280DA LDW r10,8(sp) #rem 10 000c 3A881700 MOV r11,r0 #carry 11 0010 54104003 MOVUI r13,65 # брояч _q = a_lo << 1; carry = a_lo >> 63; 12 0014 06100000 BR L4 #_/(r = a_hi;)// няма нужда от отделни q и r 13 0018 FAD71838 L1: SRLI r12,r7,31 # temp = r >> 63; 14 001c 7A900E38 SLLI r7,r7,1 15 0020 FAD71C30 SRLI r14,r6,31 16 0024 3AB08E3B OR r7,r7,r14 17 0028 7A900C30 SLLI r6,r6,1 # r = r << 1 18 002c 3AB0CC32 OR r6,r6,r11 # | carry; 19 0030 3A881760 MOV r11,r12 # carry = temp; 20 0034 1E040058 BNE r11,r0,L3 # if (carry == 0) { 21 0038 3607403A BLTU r7,r9,L4 # if (r < b) 22 003c 3601C049 BGTU r7,r9,L2 # goto shift; 23 0040 36050032 BLTU r6,r8,L4# Старшите думи са равни – сравни младшите 24 0044 4400C05A L2: ADDI r11,r11,1 # carry++; 25 0048 3A801D32 L3: CMPLTU r14,r6,r8# заем } 26 004c 3AC80D32 SUB r6,r6,r8 27 0050 3AC84F3A SUB r7,r7,r9 28 0054 3AC88F3B SUB r7,r7,r14 # r -= b; 29 0058 FAD71828 L4: SRLI r12,r5,31 #shift: temp = q >> 63; 30 005c 7A900A28 SLLI r5,r5,1 31 0060 FAD71C20 SRLI r14,r4,31 32 0064 3AB08A2B OR r5,r5,r14 33 0068 7A900820 SLLI r4,r4,1 # q = q << 1 34 006c 3AB0C822 OR r4,r4,r11 # | carry; 35 0070 3A881760 MOV r11,r12 # carry = temp; 36 0074 C4FF7F6B SUBI r13,r13,1# Следваща 37 0078 1EE73F68 BNE r13,r0,L1# итерация 38 007c 15008051 STW r6,(r10) 39 0080 1501C051 STW r7,4(r10) # *rem = r; 40 0084 3A880520 MOV r2,r4 41 0088 3A880728 MOV r3,r5 42 008c 3A2800F8 RET # return q;// Върни q в r3:r2 Xtensa GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри a3:a2 частното, а на 2 # адрес, подаден в [sp+0], да записва 64-битовия остатък от деленето на 3 # числото в регистри a5:a4:a3:a2 на числото в регистри a7:a6. 4 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 0C08 MOVI a8,0 #carry (b = a7:a6) 8 0002 4C1A MOVI a10,65 # брояч _q = a_lo << 1; carry = a_lo >> 63; 9 0004 C60B0000 00 J L5 #_/(r = a_hi;)// няма нужда от отделни q и r 10 0009 509F05 L1: EXTUI a9,a5,31,1 # temp = r >> 63; 11 000c F05511 SLLI a5,a5,1 12 000f 40BF05 EXTUI a11,a4,31,1 13 0012 B05520 OR a5,a5,a11 14 0015 F04411 SLLI a4,a4,1 # r = r << 1 15 0018 804420 OR a4,a4,a8 # | carry; 16 001b 908920 MOV a8,a9 # carry = temp; 17 001e 56A800 BNEZ a8,L3 # if (carry == 0) { 18 0021 773512 BLTU a5,a7,L5 # if (r < b) 19 0024 573702 BLTU a7,a5,L2 # goto shift; 20 0027 67340C BLTU a4,a6,L5# Старшите думи са равни – сравни младшите 21 002a 1B88 L2: ADDI a8,a8,1 # carry++; 22 002c 67B401 L3: BGEU a4,a6,L4# заем } 23 002f 0B55 ADDI a5,a5,-1 24 0031 6044C0 L4: SUB a4,a4,a6 25 0034 7055C0 SUB a5,a5,a7 # r -= b; 26 0037 309F05 L5: EXTUI a9,a3,31,1 #shift: temp = q >> 63; 27 003a F03311 SLLI a3,a3,1 28 003d 20BF05 EXTUI a11,a2,31,1 29 0040 B03320 OR a3,a3,a11 30 0043 F02211 SLLI a2,a2,1 # q = q << 1 31 0046 802220 OR a2,a2,a8 # | carry; 32 0049 8D09 MOV a8,a9 # carry = temp; 33 004b 0BAA ADDI a10,a10,-1# Следваща 34 004d 568AFB BNEZ a10,L1 # итерация 35 0050 8801 L32I a8,sp,0 #rem = a8 36 0052 4908 S32I a4,a8,0 37 0054 5918 S32I a5,a8,4 # *rem = r; 38 0056 0DF0 RET # return q;// Върни q в a3:a2 88K GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри r2:r3 частното, а на 2 # адрес, подаден в r8, да записва 64-битовия остатък от деленето на числото 3 # в регистри r4:r5:r2:r3 на числото в r6:r7. 4 5 .global _udiv128# http://codereview.stackexchange.com/questions/67962 6 0000 59400041 _udiv128: 7 0004 F4006100 or r10,r0,65#Брояч 8 0008 C000000D addu.co r0,r0,r0#C↓ ___ q = a_lo << 1; carry = a_lo >> 63; 9 000c F4A56305 br L3 #__/ (r = a_hi;)// няма нужда от отделни q и r 10 0010 F4846304 L1: addu.cio r5,r5,r5# temp = r >> 63; 11 0014 F5206200 addu.cio r4,r4,r4# r = r << 1 | carry; carry = temp; 12 0018 E9A90006 addu.ci r9,r0,r0#C=? 13 001c F5247C06 bcnd ne0,r9,L2# if (carry == 0) { 14 0020 D9490007 cmp r9,r4,r6# if (r < b) 15 0024 D9090003 bb1 lo,r9,L3#C=0 goto shift; 16 0028 F5257C07 bb1 hi,r9,L2#C=0 все още 17 002c D9490004 cmp r9,r5,r7# Старшите думи са равни – сравни младшите 18 0030 F4A56507 bb1 lo,r9,L3#C=0 ____ carry++; 19 0034 F4846606 L2: subu.co r5,r5,r7#C=1 / } 20 0038 F40A6500 subu.ci r4,r4,r6# / r -= b; 21 003c F4636303 subu.co r0,r10,r0#__/ 22 0040 F4426302 L3: addu.cio r3,r3,r3#shift: temp = q >> 63; 23 0044 654A0001 addu.cio r2,r2,r2# q = q << 1 | carry; carry = temp; 24 0048 E9AAFFF1 subu r10,r10,1 25 004c 24880000 bcnd ne0,r10,L1#Следваща итерация 26 0050 24A80004 st r4,r8,0 # *rem = r; 27 0054 F400C001 st r5,r8,4 jmp r1 # return q;// Върни q в r2:r3 Or1k GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри R11:R12 частното, а 2 # на адрес, подаден в SP(0), да записва 64-битовия остатък от деленето на 3 # числото в регистри R5:R6:R3:R4 на числото в R7:R8. 4 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 85E10000 L.LWZ R15,0(SP) # rem = R17 (b = R7:R8) 8 0004 00000012 L.J L3#изп.се след L.ADDI q = a_lo << 1; carry = a_lo >> 63; 9 0008 9D800041 L.ADDI R12,R0,65#SR[CY] = 0 (r = a_hi;)//няма нужда от отделни q и r 10 000c 9DADFFFF L1: L.ADDI R13,R13,-1 # Възстанови SR[CY] 11 0010 E5850000 L.SFLTS R5,R0 # carry = SR[F] 12 0014 E0C63001 L.ADDC R6,R6,R6 # temp = r >> 63; r = 13 0018 E0A52801 L.ADDC R5,R5,R5 # r << 1 | carry; carry = temp; 14 001c 10000008 L.BF L2#след L.SFLTU, но нищо! if (carry == 0) { 15 0020 E4853800 L.SFLTU R5,R7 # if (r < b) 16 0024 1000000A L.BF L3#след L.SFGTU, но нищо! goto shift; 17 0028 E4453800 L.SFGTU R5,R7 18 002c 10000004 L.BF L2#след L.SFLTU, но нищо! carry++; 19 0030 E4864000 L.SFLTU R6,R8 # Старшите думи са равни – сравни младшите 20 0034 10000006 L.BF L3 21 0038 15000000 L.NOP 22 003c E0C64002 L2: L.SUB R6,R6,R8 # } 23 0040 E1A70001 L.ADDC R13,R7,R0 # r -= b; 24 0044 E0A56802 L.SUB R5,R5,R13 25 0048 E1A06002 L.SUB R13,R0,R12 # Възстанови 1 в SR[CY] 26 004c E0842001 L3: L.ADDC R4,R4,R4 # shift: temp = q >> 63; q = 27 0050 E0631801 L.ADDC R3,R3,R3 # q << 1 | carry; carry = temp; 28 0054 E1A00001 L.ADDC R13,R0,R0 # Съхрани SR[CY] 29 0058 9D8CFFFF L.ADDI R12,R12,-1 # Обнови брояча 30 005c E42C0000 L.SFNE R12,R0 # Следваща итерация на цикъла? 31 0060 13FFFFEB L.BF L1 # Да, продължи (изпълн. се след L.OR, но нищо!) 32 0064 E1630004 L.OR R11,R3,R0 33 0068 E1840004 L.OR R12,R4,R0 # Не, край 34 006c D40F2800 L.SW 0(R15),R5 # *rem = r; 35 0070 44004800 L.JR LR # return q;//Върни q в R11:R12; след L.SW 36 0074 D40F3004 L.SW 4(R15),R6 Xilinx MicroBlaze GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри R4:R3 частното, а на 2 # адрес, подаден в [R1+28], да записва 64-битовия остатък от деленето на 3 # числото в регистри R8:R7:R6:R5 на числото в R10:R9. 4 5 .global udiv128 # http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 1C0061E9 LWI R11,R1,28# rem = R11 (b = R10:R9) 8 0004 41008021 ADDI R12,R0,65#↓C___ q = a_lo << 1; carry = a_lo >> 63; 9 0008 400000B8 BRI L3 #__/ (r = a_hi;)// няма нужда от отделни q и r 10 000c 0038E708 L1: ADDC R7,R7,R7# temp = r >> 63; 11 0010 00400809 ADDC R8,R8,R8# r = r << 1 | carry; carry = temp; 12 0014 FFFF402A ADDIC R18,R0,-1#C-1=? (запази C) 13 0018 240012BC BEQI R18,L2 # if (carry == 0) { 14 001c 03404A16 CMPU R18,R10,R8# if (r < b) 15 0020 00400A04 RSUB R0,R10,R8#обн.C 16 0024 240052BC BLTI R18,L3 # goto shift; 17 0028 03504816 CMPU R18,R8,R10#За R10=0,R8=2^31 CMPU R18,R10,R8 → R18=0 => без BGTI 18 002c 100052BC BLTI R18,L2 19 0030 03384916 CMPU R18,R9,R7# Старшите думи са равни – сравни младшите 20 0034 00380904 RSUB R0,R9,R7#обн.C 21 0038 100052BC BLTI R18,L3 #C=0 ____ carry++; 22 003c 0038E904 L2: RSUB R7,R9,R7#C=1 / } 23 0040 00400A0D RSUBC R8,R10,R8# / r -= b; 24 0044 00000004 RSUB R0,R0,R0#___/ 25 0048 0028A508 L3: ADDC R5,R5,R5#shift: temp = q >> 63; 26 004c 0030C608 ADDC R6,R6,R6# q = q << 1 | carry; carry = temp; 27 0050 FFFF8C31 ADDIK R12,R12,-1# Обнови брояча 28 0054 B8FF2CBC BNEI R12,L1 # Следваща итерация 29 0058 04000BF9 SWI R8,R11,4# *rem = r; 30 005c 0000EBF8 SWI R7,R11,0 31 0060 00008680 OR R4,R6,R0 32 0064 08000FB6 RTSD R15,8 # return q; 33 0068 00006580 OR R3,R5,R0# Върни q в R4:R3 (изпълнява се преди „RTSD“!) HPPA GAS udiv128.s page 1 1 ; Да се напише подпрограма, която да връща в регистри %R28:%R29 частното, а 2 ; на адрес, подаден в (%SP-60), да записва остатъка от деленето на числото в 3 ; регистри %R23:%R24:%R25:%R26 на числото в (%SP-56):(%SP-52) 4 5 .text 6 .global udiv128 ; http://codereview.stackexchange.com/questions/67962 7 udiv128: 8 0000 4BD63F99 LDW -52(%SP),%R22 9 0004 4BD53F91 LDW -56(%SP),%R21 ; b = %R21:%R22 10 0008 4BD43F89 LDW -60(%SP),%R20 ; rem = %R20 11 000c E8000048 B L3;(C = 0 след „ADDI“) q = a_lo << 1; carry = a_lo >> 63; 12 0010 B4010082 ADDI 65,%R0,%R1 ;Брч (r = a_hi;)//няма нужда от отделни q и r 13 0014 0B180718 L1: ADDC %R24,%R24,%R24 ; temp = r>>63; r = 14 0018 0AF78717 ADDC,NUV %R23,%R23,%R23 ; r<<1 | carry; carry = temp; 15 001c E8000012 B,N L2 ; if(carry == 0) { 16 0020 0AD80400 SUB %R24,%R22,%R0 17 0024 0AB79500 SUBB,>>= %R23,%R21,%R0 ; if (r < b) 18 0028 E8000012 B,N L3 ; C = 0 goto shift; 19 002c 0AD80418 L2: SUB %R24,%R22,%R24 ; C = 1 ____________ carry++; 20 0030 0AB70517 SUBB %R23,%R21,%R23 ;________ / } 21 0034 08000400 SUB %R0,%R0,%R0 ;________X_____ r -= b; 22 0038 0B5A071A L3: ADDC %R26,%R26,%R26 ; shift: temp = q >> 63; q = 23 003c AC3F3FA5 ADDIBF,= -1,%R1,L1; Следваща итерация на цикъла (изпълн.се след „ADDC“) 24 0040 0B390719 ADDC %R25,%R25,%R25 ; q << 1 | carry; carry = temp; 25 0044 0E971280 STWS %R23,0(%R20) 26 0048 0E981288 STWS %R24,4(%R20) ; *rem = r; 27 004c 0819025C COPY %R25,%R28 28 0050 E840C000 BV (%R2) ; return q; 29 0054 081A025D COPY %R26,%R29 ; Върни q в %R28:%R29 (изпълнява се преди „BV“) Renesas / SuperH SH GAS Little Endian udiv128.s page 1 1 ! Да се напише подпрограма, която да връща в регистри R1:R0 частното, а на 2 ! адрес, подаден в (SP+8), да записва 64-битовия остатък от деленето на 3 ! числото в регистри R7:R6:R5:R4 на числото в (SP+4):(SP). 4 5 .global udiv128 ! http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 F262 MOV.L @SP,R2 ! Младша дума на делителя 8 0002 F153 MOV.L @(4,SP),R3 ! Старша дума на делителя (b = R3:R2) 9 0004 0800 CLRT ! Нулирай преноса 10 0006 41E1 MOV #65,R1 ! Брч q = a_lo << 1; carry = a_lo >> 63; 11 0008 0D8B BF L3 ! (r = a_hi;)//няма нужда от отделни q и r 12 000a 0140 L1: SHLR R0 ! Възстанови T 13 000c 6E36 ADDC R6,R6 ! temp = r >> 63; r = 14 000e 7E37 ADDC R7,R7 ! r << 1 | carry; carry = temp; 15 0010 0589 BT L2 ! if (carry == 0) { 16 0012 3237 CMP/HS R3,R7 ! if (r < b) 17 0014 078B BF L3 ! goto shift; 18 0016 3637 CMP/HI R3,R7 19 0018 0189 BT L2 ! T = 1 carry++; 20 001a 2236 CMP/HS R2,R6 ! Старшите думи са равни – сравни младшите 21 001c 038B BF L3 22 001e 0800 L2: CLRT ! } 23 0020 2A36 SUBC R2,R6 24 0022 3A37 SUBC R3,R7 ! r -= b; 25 0024 1800 SETT ! Възстанови 1 в T 26 0026 4E34 L3: ADDC R4,R4 ! shift: temp = q >> 63; q = 27 0028 5E35 ADDC R5,R5 ! q << 1 | carry; carry = temp; 28 002a 2900 MOVT R0 ! Съхрани T 29 002c 1041 DT R1 ! Следваща итерация на цикъла? 30 002e EC8B BF L1 ! Да, продължи 31 0030 F250 MOV.L @(8,SP),R0 ! rem = R0 32 0032 6220 MOV.L R6,@R0 33 0034 7110 MOV.L R7,@(4,R0) ! *rem = r; 34 0036 4360 MOV R4,R0 35 0038 0B00 RTS ! return q;//Върни q в R1:R0 36 003a 5361 MOV R5,R1 ! Изпълнява се преди „RTS“ GAS for CRIS udiv128.s page 1 1 ; Да се напише подпрограма, която да връща в регистри R11:R10 частното, а на 2 ; адрес, подаден в [SP+8], да записва 64-битовия остатък от деленето на 3 ; числото в регистри R13:R12:R11:R10 на числото в [SP+4]:[SP]. 4 5 .global udiv128 ; http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 90E2 SUBQ 16,$SP ;_Съхрани R0–R3 (ETRAX FS Designer’s Reference, стр.212 8 0002 FE3B MOVEM $R3,[$SP];\_C=0 9 0004 10E1 ADDOQ 16,$SP,$ACR 10 0006 BF2B MOVEM [$ACR],$R2 ; rem = R2 (b = R1:R0) 11 0008 24E0 BA L3;изпълн.се след MOVU q = a_lo << 1; carry = a_lo >> 63; 12 000a 4F3C4100 MOVU.B 65,$R3 ; (r = a_hi;)//няма нужда от отделни q и r 13 000e 39D6 L1: MOVE $R9,$CCS ; Възстанови C 14 0010 7CC5 ADDC $R12,$R12 ; temp = r >> 63; r = 15 0012 7DD5 ADDC $R13,$R13 ; r << 1 | carry; carry = temp; 16 0014 1010 BCS L2;след CMP, но нищо! if (carry == 0) { 17 0016 ED16 CMP.D $R13,$R1 ; if (r < b) 18 0018 1490 BHI L3 ; C || Z = 0 goto shift; 19 001a B005 NOP ; C || Z = 1 20 001c 0810 BLO L2;след CMP, но нищо! C = 1 _______ carry++; 21 001e EC06 CMP.D $R12,$R0 ; Старшите думи/са равни – сравни младшите 22 0020 0C90 BHI L3 ; / 23 0022 B005 NOP ; / 24 0024 A0C6 L2: SUB.D $R0,$R12 ; / } 25 0026 B015 AX ; / r -= b; 26 0028 A1D6 SUB.D $R1,$R13 ; / 27 002a B105 SETF C ;________/ 28 002c 7AA5 L3: ADDC $R10,$R10 ; shift: temp = q >> 63; q = 29 002e 7BB5 ADDC $R11,$R11 ; q << 1 | carry; carry = temp; 30 0030 79D6 MOVE $CCS,$R9 ; Съхрани C 31 0032 8132 SUBQ 1,$R3 ; Следваща итерация на цикъла? 32 0034 DB20 BNE L1 ; Да, продължи 33 0036 B005 NOP 34 0038 E2CF MOVE.D $R12,[$R2+] 35 003a E2DB MOVE.D $R13,[$R2] ; *rem = r; 36 003c F0B9 RET ; return q;//Възст. и върни q в R11:R10 37 003e BE3F MOVEM [$SP+],$R3 ; Изпълнява се преди „RET“! BFIN GAS udiv128.s page 1 1 # Да се напише подпрограма, която да връща в регистри R1:R0 частното, а на 2 # адрес, подаден в [SP+24], да записва остатъка от деленето на числото в 3 # [SP+12]:R2:R1:R0 на числото в [SP+20]:[SP+16]. 4 5 .global _udiv128# http://codereview.stackexchange.com/questions/67962 6 _udiv128: 7 0000 00E80000 LINK 0; # Създай стекова рамка 8 0004 E305 [--SP] = (R7:4, P5:3);# Съхрани R4–R7/P3–P5 (82-000410-03, стр. 1-433) 9 0006 7BA1 R3 = [FP + 20]; # R3:R2:R1:R0 = a (R3:R2 = a_hi, R1:R0 = a_lo), делимо 10 0008 BCA1 R4 = [FP + 24]; 11 000a FDA1 R5 = [FP + 28]; # R5:R4 = b, делител 12 000c 38AE P0 = [FP + 32]; # P0 = rem, адрес на остатъка 13 000e C008 CC = P0 < P0; # Нулирай CC 14 0010 82C608C0 R0 = ROT R0 BY 1;#q = a_lo << 1;(r = a_hi;)//няма нужда от отделни q, r 15 0014 82C609C2 R1 = ROT R1 BY 1;#carry = a_lo >> 31; 16 0018 29E14000 P1 = 64; # Брой итерации 17 001c A2E01510 LSETUP (L_1, L_4) LC0 = P1; 18 0020 82C60AC4 L_1: R2 = ROT R2 BY 1; # temp = r >> 31; r = r << 1 | carry; carry = temp; 19 0024 82C60BC6 R3 = ROT R3 BY 1; 20 0028 0718 IF CC JUMP L_2; # if (carry == 0) { 21 002a 1D0A CC = R5 <= R3 (IU);# if (r < b) 22 002c 0B10 IF !CC JUMP L_3; #r < b 23 002e 9D09 CC = R5 < R3 (IU); 24 0030 0318 IF CC JUMP L_2; #r > b 25 0032 140A CC = R4 <= R2 (IU);# Старшите думи са равни – сравни младшите 26 0034 0710 IF !CC JUMP L_3; # goto shift; (carry++;)// CC вече е лог. 1 27 0036 A252 L_2: R2 = R2 - R4; # } r -= b; 28 0038 0C03 CC = AC0; # AC0 обратен след изваждане: 82-000556-01 стр. 11-3 29 003a EB52 R3 = R3 - R5; 30 003c 0318 IF CC JUMP L_3; 31 003e FB67 R3 += -1; 32 0040 1802 CC = !CC; # CC = 1 33 0042 82C608C0 L_3: R0 = ROT R0 BY 1;#shift:temp=q >> 31; q = q << 1 | carry; carry = temp; 34 0046 82C609C2 L_4: R1 = ROT R1 BY 1; 35 004a 0292 [P0++] = R2; # *rem = r; // Запиши остатъка по дадения адрес (LE) 36 004c 0393 [P0] = R3; 37 004e A305 (R7:4, P5:3) = [SP++];# Възстанови съхранените регистри 38 0050 01E80000 UNLINK; # Затвори стековата рамка 39 0054 10000000 RTS; # return q; // Върни частното в R1:R0 Hexagon GAS udiv128.s page 1 1 // Да се напише подпрограма, която да връща в регистри R1:R0 частното, а на 2 // адрес, подаден в [SP+0], да записва 64-битовия остатък от деленето на 3 // числото в регистри R3:R2:R1:R0 на числото в R5:R4. 4 5 .global udiv128 // http://codereview.stackexchange.com/questions/67962 6 udiv128: 7 0000 00C040F2 { P0 = CMP.GT(R0,R0) } //P0=0 8 { LOOP0 (L1,#64) //Брч q = a_lo << 1; carry = a_lo >> 63; 9 0004 10400269 00C0C0C2 R1:0 = ADD(R1:0,R1:0,P0):CARRY}//(r=a_hi;)//няма нужда от отделни q, r 10 000c 02C2C2C2 L1: R3:2 = ADD(R3:2,R3:2,P0):CARRY// temp = r>>63; r = r<<1 | carry; 11 { IF (P0) JUMP L2 // carry = temp; if (carry == 0) { 12 0010 0840005C 81C284D2 P1 = CMP.GTU(R5:4,R3:2) }// if (r < b) 13 0018 06C1005C IF (P1) JUMP L3 // goto shift; 14 001c 00C000F2 P0 = CMP.EQ(R0,R0) //P0=!0 carry++; 15 0020 E2C224D3 L2: R3:2 = SUB(R3:2,R5:4) // } r -= b; 16 0024 0080C0C2 00C0007F L3: { R1:0 = ADD(R1:0,R1:0,P0):CARRY }:ENDLOOP0//shift:temp = q >> 63; 17 002c 06C09D91 R6 = MEMW(SP) //rem q = q<<1 | carry; carry = temp; 18 { MEMD(R6) = R3:2 // *rem = r; 19 0030 00409F52 00C2C6A1 JUMPR LR } // return q; // Върни q в R1:R0