]> git.cryptolib.org Git - avr-crypto-lib.git/blob - shacal1/sha1-asm.S
f571685984c5046fd0f4280adbc9a5fe513720a8
[avr-crypto-lib.git] / shacal1 / sha1-asm.S
1 /* sha1-asm.S */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /*
20  * Author:      Daniel Otte
21  *
22  * License: GPLv3 or later
23 */
24 ; SHA1 implementation in assembler for AVR
25 SHA1_BLOCK_BITS = 512
26 SHA1_HASH_BITS = 160
27
28 .macro precall
29         /* push r18 - r27, r30 - r31*/
30         push r0
31         push r1
32         push r18
33         push r19
34         push r20
35         push r21
36         push r22
37         push r23
38         push r24
39         push r25
40         push r26
41         push r27
42         push r30
43         push r31
44         clr r1
45 .endm
46
47 .macro postcall
48         pop r31
49         pop r30
50         pop r27
51         pop r26
52         pop r25
53         pop r24
54         pop r23
55         pop r22
56         pop r21
57         pop r20
58         pop r19
59         pop r18
60         pop r1
61         pop r0
62 .endm
63
64
65 .macro hexdump length
66         push r27
67         push r26
68         ldi r25, '\r'
69         mov r24, r25
70         call uart_putc
71         ldi r25, '\n'
72         mov r24, r25
73         call uart_putc
74         pop r26
75         pop r27
76         movw r24, r26
77 .if \length > 16
78         ldi r22, lo8(16)
79         ldi r23, hi8(16)
80         push r27
81         push r26
82         call uart_hexdump
83         pop r26
84         pop r27
85         adiw r26, 16
86         hexdump \length-16
87 .else
88         ldi r22, lo8(\length)
89         ldi r23, hi8(\length)
90         call uart_hexdump
91 .endif
92 .endm
93
94 .macro delay
95 /*      
96         push r0
97         push r1
98         clr r0
99 1:      clr r1
100 2:      dec r1
101         brne 2b
102         dec r0
103         brne 1b
104         pop r1
105         pop r0  // */
106 .endm
107
108 /* X points to Block */
109 .macro dbg_hexdump length
110 /*      
111         precall
112         hexdump \length
113         postcall
114         // */
115 .endm
116
117
118
119 .section .text
120
121 SPL = 0x3D
122 SPH = 0x3E
123 SREG = 0x3F
124
125
126 ;
127 ;sha1_ctx_t is:
128 ;
129 ; [h0][h1][h2][h3][h4][length]
130 ; hn is 32 bit large, length is 64 bit large
131
132 ;###########################################################    
133
134 .global sha1_ctx2hash
135 ; === sha1_ctx2hash ===
136 ; this function converts a state into a normal hash (bytestring)
137 ;  param1: the 16-bit destination pointer
138 ;       given in r25,r24 (r25 is most significant)
139 ;  param2: the 16-bit pointer to sha1_ctx structure
140 ;       given in r23,r22
141 sha1_ctx2hash:
142         movw r26, r22
143         movw r30, r24
144         ldi r21, 5
145         sbiw r26, 4
146 1:      
147         ldi r20, 4
148         adiw r26, 8
149 2:      
150                 ld r0, -X
151                 st Z+, r0       
152         dec r20
153         brne 2b
154         
155         dec r21
156         brne 1b
157         
158         ret
159
160 ;###########################################################    
161
162 .global sha1
163 ; === sha1 ===
164 ; this function calculates SHA-1 hashes from messages in RAM
165 ;  param1: the 16-bit hash destination pointer
166 ;       given in r25,r24 (r25 is most significant)
167 ;  param2: the 16-bit pointer to message
168 ;       given in r23,r22
169 ;  param3: 32-bit length value (length of message in bits)
170 ;   given in r21,r20,r19,r18
171 sha1:
172 sha1_prolog:
173         push r8
174         push r9
175         push r10
176         push r11
177         push r12
178         push r13
179         push r16
180         push r17
181         in r16, SPL
182         in r17, SPH
183         subi r16, 5*4+8 
184         sbci r17, 0     
185         in r0, SREG
186         cli
187         out SPL, r16
188         out SPH, r17
189         out SREG, r0
190         
191         push r25
192         push r24
193         inc r16
194         adc r17, r1
195         
196         movw r8, r18            /* backup of length*/
197         movw r10, r20
198         
199         movw r12, r22   /* backup pf msg-ptr */
200         
201         movw r24, r16
202         rcall sha1_init
203         /* if length >= 512 */
204 1:
205         tst r11
206         brne 4f
207         tst r10
208         brne 4f
209         mov r19, r9
210         cpi r19, 0x02
211         brlo 4f
212         
213         movw r24, r16
214         movw r22, r12
215         rcall sha1_nextBlock
216         ldi r19, 0x64
217         add r22, r19
218         adc r23, r1
219         /* length -= 512 */
220         ldi r19, 0x02
221         sub r9, r19
222         sbc r10, r1
223         sbc r11, r1
224         rjmp 1b
225         
226 4:
227         movw r24, r16
228         movw r22, r12
229         movw r20, r8
230         rcall sha1_lastBlock
231         
232         pop r24
233         pop r25
234         movw r22, r16
235         rcall sha1_ctx2hash     
236         
237 sha1_epilog:
238         in r30, SPL
239         in r31, SPH
240         adiw r30, 5*4+8         
241         in r0, SREG
242         cli
243         out SPL, r30
244         out SPH, r31
245         out SREG, r0
246         pop r17
247         pop r16
248         pop r13
249         pop r12
250         pop r11
251         pop r10
252         pop r9
253         pop r8
254         ret
255
256 ;###########################################################    
257
258
259 ; block MUST NOT be larger than 64 bytes
260
261 .global sha1_lastBlock
262 ; === sha1_lastBlock ===
263 ; this function does padding & Co. for calculating SHA-1 hashes
264 ;  param1: the 16-bit pointer to sha1_ctx structure
265 ;       given in r25,r24 (r25 is most significant)
266 ;  param2: an 16-bit pointer to 64 byte block to hash
267 ;       given in r23,r22
268 ;  param3: an 16-bit integer specifing length of block in bits
269 ;       given in r21,r20
270 sha1_lastBlock_localSpace = (SHA1_BLOCK_BITS/8+1)
271
272
273 sha1_lastBlock:
274         cpi r21, 0x02
275         brlo sha1_lastBlock_prolog
276         push r25
277         push r24
278         push r23
279         push r22
280         push r21
281         push r20
282         rcall sha1_nextBlock
283         pop r20
284         pop r21
285         pop r22
286         pop r23
287         pop r24
288         pop r25
289         subi r21, 2
290         subi r23, -2
291         rjmp sha1_lastBlock
292 sha1_lastBlock_prolog:
293         /* allocate space on stack */
294         in r30, SPL
295         in r31, SPH
296         in r1, SREG
297         subi r30, lo8(64)
298         sbci r31, hi8(64) /* ??? */
299         cli
300         out SPL, r30
301         out SPH, r31
302         out SREG,r1
303
304         adiw r30, 1 /* SP points to next free byte on stack */
305         mov r18, r20 /* r20 = LSB(length) */
306         lsr r18
307         lsr r18
308         lsr r18
309         bst r21, 0      /* may be we should explain this ... */
310         bld r18, 5  /* now: r18 == length/8 (aka. length in bytes) */
311         
312         
313         movw r26, r22 /* X points to begin of msg */
314         tst r18
315         breq sha1_lastBlock_post_copy
316         mov r1, r18
317 sha1_lastBlock_copy_loop:
318         ld r0, X+
319         st Z+, r0
320         dec r1
321         brne sha1_lastBlock_copy_loop
322 sha1_lastBlock_post_copy:       
323 sha1_lastBlock_insert_stuffing_bit:     
324         ldi r19, 0x80
325         mov r0,r19      
326         ldi r19, 0x07
327         and r19, r20 /* if we are in bitmode */
328         breq 2f /* no bitmode */
329 1:      
330         lsr r0
331         dec r19
332         brne 1b
333         ld r19, X
334 /* maybe we should do some ANDing here, just for safety */
335         or r0, r19
336 2:      
337         st Z+, r0
338         inc r18
339
340 /* checking stuff here */
341         cpi r18, 64-8+1
342         brsh 0f 
343         rjmp sha1_lastBlock_insert_zeros
344 0:
345         /* oh shit, we landed here */
346         /* first we have to fill it up with zeros */
347         ldi r19, 64
348         sub r19, r18
349         breq 2f
350 1:      
351         st Z+, r1
352         dec r19
353         brne 1b 
354 2:      
355         sbiw r30, 63
356         sbiw r30,  1
357         movw r22, r30
358         
359         push r31
360         push r30
361         push r25
362         push r24
363         push r21
364         push r20
365         rcall sha1_nextBlock
366         pop r20
367         pop r21
368         pop r24
369         pop r25
370         pop r30
371         pop r31
372         
373         /* now we should subtract 512 from length */
374         movw r26, r24
375         adiw r26, 4*5+1 /* we can skip the lowest byte */
376         ld r19, X
377         subi r19, hi8(512)
378         st X+, r19
379         ldi r18, 6
380 1:
381         ld r19, X
382         sbci r19, 0
383         st X+, r19
384         dec r18
385         brne 1b
386         
387 ;       clr r18 /* not neccessary ;-) */
388         /* reset Z pointer to begin of block */
389
390 sha1_lastBlock_insert_zeros:    
391         ldi r19, 64-8
392         sub r19, r18
393         breq sha1_lastBlock_insert_length
394         clr r1
395 1:
396         st Z+, r1       /* r1 is still zero */
397         dec r19
398         brne 1b
399
400 ;       rjmp sha1_lastBlock_epilog
401 sha1_lastBlock_insert_length:
402         movw r26, r24   /* X points to state */
403         adiw r26, 5*4   /* X points to (state.length) */
404         adiw r30, 8             /* Z points one after the last byte of block */
405         ld r0, X+
406         add r0, r20
407         st -Z, r0
408         ld r0, X+
409         adc r0, r21
410         st -Z, r0
411         ldi r19, 6
412 1:
413         ld r0, X+
414         adc r0, r1
415         st -Z, r0
416         dec r19
417         brne 1b
418
419         sbiw r30, 64-8
420         movw r22, r30
421         rcall sha1_nextBlock
422
423 sha1_lastBlock_epilog:
424         in r30, SPL
425         in r31, SPH
426         in r1, SREG
427         adiw r30, 63 ; lo8(64)
428         adiw r30,  1  ; hi8(64)
429         cli
430         out SPL, r30
431         out SPH, r31
432         out SREG,r1
433         clr r1
434         clr r0
435         ret
436
437 /**/
438 ;###########################################################    
439
440 .global sha1_nextBlock
441 ; === sha1_nextBlock ===
442 ; this is the core function for calculating SHA-1 hashes
443 ;  param1: the 16-bit pointer to sha1_ctx structure
444 ;       given in r25,r24 (r25 is most significant)
445 ;  param2: an 16-bit pointer to 64 byte block to hash
446 ;       given in r23,r22
447 sha1_nextBlock_localSpace = (16+5+1)*4 ; 16 32-bit values for w array and 5 32-bit values for a array (total 84 byte)
448
449 xtmp = 0
450 xNULL = 1
451 W1 = 10
452 W2 = 11
453 T1      = 12
454 T2      = 13
455 T3      = 14
456 T4      = 15
457 LoopC = 16
458 S         = 17
459 tmp1 = 18
460 tmp2 = 19
461 tmp3 = 20
462 tmp4 = 21
463 F1 = 22
464 F2 = 23
465 F3 = 24
466 F4 = 25
467
468 /* byteorder: high number <--> high significance */
469 sha1_nextBlock:
470  ; initial, let's make some space ready for local vars
471                          /* replace push & pop by mem ops? */
472         push r10
473         push r11
474         push r12
475         push r13
476         push r14
477         push r15
478         push r16
479         push r17
480         push r28
481         push r29
482         in r20, SPL
483         in r21, SPH
484         movw r18, r20                   ;backup SP
485 ;       movw r26, r20                   ; X points to free space on stack /* maybe removeable? */ 
486         movw r30, r22                   ; Z points to message
487         subi r20, lo8(sha1_nextBlock_localSpace) ;sbiw can do only up to 63
488         sbci r21, hi8(sha1_nextBlock_localSpace)
489         movw r26, r20                   ; X points to free space on stack 
490         in r0, SREG
491         cli ; we want to be uninterrupted while updating SP
492         out SPL, r20
493         out SPH, r21
494         out SREG, r0
495         
496         push r18
497         push r19 /* push old SP on new stack */
498         push r24
499         push r25 /* param1 will be needed later */
500         
501         /* load a[] with state */
502         movw 28, r24 /* load pointer to state in Y */
503         adiw r26, 1 ; X++
504
505         ldi LoopC, 5*4  
506 1:      ld tmp1, Y+
507         st X+, tmp1
508         dec LoopC
509         brne 1b
510
511         movw W1, r26 /* save pointer to w[0] */
512         /* load w[] with endian fixed message */
513                 /* we might also use the changeendian32() function at bottom */
514         movw r30, r22 /* mv param2 (ponter to msg) to Z */      
515         ldi LoopC, 16
516 1:
517         ldd tmp1, Z+3
518         st X+, tmp1
519         ldd tmp1, Z+2
520         st X+, tmp1
521         ldd tmp1, Z+1
522         st X+, tmp1
523         ld tmp1, Z
524         st X+, tmp1
525         adiw r30, 4
526         dec LoopC
527         brne 1b
528         
529         ;clr LoopC /* LoopC is named t in FIPS 180-2 */ 
530         clr xtmp
531 sha1_nextBlock_mainloop:
532         mov S, LoopC
533         lsl S
534         lsl S
535         andi S, 0x3C /* S is a bytepointer so *4 */
536         /* load w[s] */
537         movw r26, W1
538         add r26, S /* X points at w[s] */
539         adc r27, xNULL
540         ld T1, X+
541         ld T2, X+
542         ld T3, X+
543         ld T4, X+
544
545         /**/
546         push r26
547         push r27
548         push T4
549         push T3
550         push T2
551         push T1
552         in r26, SPL
553         in r27, SPH
554         adiw r26, 1
555         dbg_hexdump 4
556         pop T1
557         pop T2
558         pop T3
559         pop T4
560         pop r27
561         pop r26
562         /**/
563
564         cpi LoopC, 16
565         brlt sha1_nextBlock_mainloop_core
566         /* update w[s] */
567         ldi tmp1, 2*4
568         rcall 1f
569         ldi tmp1, 8*4
570         rcall 1f
571         ldi tmp1, 13*4
572         rcall 1f
573         rjmp 2f
574 1:              /* this might be "outsourced" to save the jump above */
575         add tmp1, S
576         andi tmp1, 0x3f
577         movw r26, W1
578         add r26, tmp1
579         adc r27, xNULL
580         ld tmp2, X+
581         eor T1, tmp2
582         ld tmp2, X+
583         eor T2, tmp2
584         ld tmp2, X+
585         eor T3, tmp2
586         ld tmp2, X+
587         eor T4, tmp2
588         ret
589 2:      /* now we just hav to do a ROTL(T) and save T back */
590         mov tmp2, T4
591         rol tmp2
592         rol T1
593         rol T2
594         rol T3
595         rol T4
596         movw r26, W1
597         add r26, S
598         adc r27, xNULL
599         st X+, T1
600         st X+, T2
601         st X+, T3
602         st X+, T4
603         
604 sha1_nextBlock_mainloop_core:   /* ther core function; T=ROTL5(a) ....*/        
605                                                                 /* T already contains w[s] */
606         movw r26, W1
607         sbiw r26, 4*1           /* X points at a[4] aka e */
608         ld tmp1, X+ 
609         add T1, tmp1
610         ld tmp1, X+ 
611         adc T2, tmp1
612         ld tmp1, X+ 
613         adc T3, tmp1
614         ld tmp1, X+ 
615         adc T4, tmp1            /* T = w[s]+e */
616         sbiw r26, 4*5           /* X points at a[0] aka a */
617         ld F1, X+ 
618         ld F2, X+ 
619         ld F3, X+ 
620         ld F4, X+ 
621         mov tmp1, F4            /* X points at a[1] aka b */
622         ldi tmp2, 5
623 1:
624         rol tmp1
625         rol F1
626         rol F2
627         rol F3
628         rol F4
629         dec tmp2
630         brne 1b
631         
632         add T1, F1
633         adc T2, F2
634         adc T3, F3
635         adc T4, F4 /* T = ROTL(a,5) + e + w[s] */
636         
637         /* now we have to do this fucking conditional stuff */
638         ldi r30, lo8(sha1_nextBlock_xTable)
639         ldi r31, hi8(sha1_nextBlock_xTable)
640         add r30, xtmp
641         adc r31, xNULL
642         lpm tmp1, Z
643         cp tmp1, LoopC
644         brne 1f
645         inc xtmp
646 1:      ldi r30, lo8(sha1_nextBlock_KTable)
647         ldi r31, hi8(sha1_nextBlock_KTable)
648         lsl xtmp
649         lsl xtmp
650         add r30, xtmp
651         adc r31, xNULL
652         lsr xtmp
653         lsr xtmp
654          
655         lpm tmp1, Z+
656         add T1, tmp1
657         lpm tmp1, Z+
658         adc T2, tmp1
659         lpm tmp1, Z+
660         adc T3, tmp1
661         lpm tmp1, Z+
662         adc T4, tmp1
663                         /* T = ROTL(a,5) + e + kt + w[s] */
664         
665         /* Z-4 is just pointing to kt ... */
666         movw r28, r26 /* copy X in Y */
667         adiw r30, 3*4 /* now Z points to the rigth locatin in our jump-vector-table */
668         lsr r31
669         ror r30
670                 
671         icall
672         mov F1, tmp1
673         icall
674         mov F2, tmp1
675         icall
676         mov F3, tmp1
677         icall
678         
679         add T1, F1
680         adc T2, F2
681         adc T3, F3
682         adc T4, tmp1 /* T = ROTL5(a) + f_t(b,c,d) + e + k_t + w[s] */
683                                  /* X points still at a[1] aka b, Y points at a[2] aka c */     
684         /* update a[] */
685 sha1_nextBlock_update_a:
686         /*first we move all vars in a[] "one up" e=d, d=c, c=b, b=a*/
687         //adiw r28, 3*4  /* Y should point at a[4] aka e */
688         movw r28, W1
689         sbiw r28, 4
690         
691         ldi tmp2, 4*4 
692 1:      
693         ld tmp1, -Y
694         std Y+4, tmp1
695         dec tmp2
696         brne 1b
697         /* Y points at a[0] aka a*/
698         
699         movw r28, W1
700         sbiw r28, 5*4
701         /* store T in a[0] aka a */
702         st Y+, T1
703         st Y+, T2
704         st Y+, T3
705         st Y+, T4
706         /* Y points at a[1] aka b*/
707         
708         /* rotate c */
709         ldd T1, Y+1*4
710         ldd T2, Y+1*4+1
711         ldd T3, Y+1*4+2
712         ldd T4, Y+1*4+3
713         mov tmp1, T1
714         ldi tmp2, 2
715 1:      ror tmp1
716         ror T4
717         ror T3
718         ror T2
719         ror T1
720         dec tmp2
721         brne 1b
722         std Y+1*4+0, T1
723         std Y+1*4+1, T2
724         std Y+1*4+2, T3
725         std Y+1*4+3, T4
726         
727         push r27
728         push r26
729         movw r26, W1
730         sbiw r26, 4*5
731         dbg_hexdump 4*5
732         pop r26
733         pop r27
734         
735         inc LoopC
736         cpi LoopC, 80
737         brge 1f
738         rjmp sha1_nextBlock_mainloop
739 /**************************************/
740 1:      
741    /* littel patch */
742         sbiw r28, 4
743
744 /* add a[] to state and inc length */   
745         pop r27
746         pop r26         /* now X points to state (and Y still at a[0]) */
747         ldi tmp4, 5
748 1:      clc
749         ldi tmp3, 4
750 2:      ld tmp1, X
751         ld tmp2, Y+
752         adc tmp1, tmp2
753         st X+, tmp1
754         dec tmp3
755         brne 2b
756         dec tmp4
757         brne 1b
758         
759         /* now length += 512 */
760         adiw r26, 1 /* we skip the least significant byte */
761         ld tmp1, X
762         ldi tmp2, hi8(512) /* 2 */
763         add tmp1, tmp2
764         st X+, tmp1
765         ldi tmp2, 6
766 1:
767         ld tmp1, X
768         adc tmp1, xNULL
769         st X+, tmp1
770         dec tmp2
771         brne 1b
772         
773 ; EPILOG
774 sha1_nextBlock_epilog:
775 /* now we should clean up the stack */
776         pop r21
777         pop r20
778         in r0, SREG
779         cli ; we want to be uninterrupted while updating SP
780         out SPL, r20
781         out SPH, r21
782         out SREG, r0
783         
784         clr r1
785         pop r29
786         pop r28
787         pop r17
788         pop r16
789         pop r15
790         pop r14
791         pop r13
792         pop r12
793         pop r11
794         pop r10
795         ret
796
797 sha1_nextBlock_xTable:
798 .byte 20,40,60,0
799 sha1_nextBlock_KTable:
800 .int    0x5a827999 
801 .int    0x6ed9eba1 
802 .int    0x8f1bbcdc 
803 .int    0xca62c1d6
804 sha1_nextBlock_JumpTable:
805 rjmp sha1_nextBlock_Ch
806         nop     
807 rjmp sha1_nextBlock_Parity
808         nop
809 rjmp sha1_nextBlock_Maj
810         nop
811 rjmp sha1_nextBlock_Parity
812
813          /* X and Y still point at a[1] aka b ; return value in tmp1 */
814 sha1_nextBlock_Ch:
815         ld tmp1, Y+
816         mov tmp2, tmp1
817         com tmp2
818         ldd tmp3, Y+3   /* load from c */
819         and tmp1, tmp3
820         ldd tmp3, Y+7   /* load from d */
821         and tmp2, tmp3
822         eor tmp1, tmp2
823         ret
824         
825 sha1_nextBlock_Maj:
826         ld tmp1, Y+
827         mov tmp2, tmp1
828         ldd tmp3, Y+3   /* load from c */
829         and tmp1, tmp3
830         ldd tmp4, Y+7   /* load from d */
831         and tmp2, tmp4
832         eor tmp1, tmp2
833         and tmp3, tmp4
834         eor tmp1, tmp3
835         ret
836
837 sha1_nextBlock_Parity:
838         ld tmp1, Y+
839         ldd tmp2, Y+3   /* load from c */
840         eor tmp1, tmp2
841         ldd tmp2, Y+7   /* load from d */
842         eor tmp1, tmp2
843         ret
844 /*      
845 ch_str:                 .asciz "\r\nCh"
846 maj_str:                .asciz "\r\nMaj"
847 parity_str:     .asciz "\r\nParity"
848 */
849 ;###########################################################    
850
851 .global sha1_init 
852 ;void sha1_init(sha1_ctx_t *state){
853 ;       DEBUG_S("\r\nSHA1_INIT");
854 ;       state->h[0] = 0x67452301;
855 ;       state->h[1] = 0xefcdab89;
856 ;       state->h[2] = 0x98badcfe;
857 ;       state->h[3] = 0x10325476;
858 ;       state->h[4] = 0xc3d2e1f0;
859 ;       state->length = 0;
860 ;}
861 ; param1: (Func3,r24) 16-bit pointer to sha1_ctx_t struct in ram
862 ; modifys: Z(r30,r31), Func1, r22
863 sha1_init:
864         movw r26, r24 ; (24,25) --> (26,27) load X with param1
865         ldi r30, lo8((sha1_init_vector))
866         ldi r31, hi8((sha1_init_vector))
867         ldi r22, 5*4 /* bytes to copy */
868 sha1_init_vloop:        
869         lpm r23, Z+ 
870         st X+, r23
871         dec r22
872         brne sha1_init_vloop
873         ldi r22, 8
874 sha1_init_lloop:
875         st X+, r1
876         dec r22
877         brne sha1_init_lloop
878         ret
879         
880 sha1_init_vector:
881 .int 0x67452301;
882 .int 0xefcdab89;
883 .int 0x98badcfe;
884 .int 0x10325476;
885 .int 0xc3d2e1f0;
886