Sign in Join
Wiki copytemporary

Assembler and ABI Resources: what changed

Revision 3 to 4. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## The Assembler
22
33The FPC Pascal Compiler translates Pascal source code into assembly language which is then processed by an assembler running as a separate backend. Some other Pascal compilers directly generate object modules or executable programs directly, i.e. they do not require a separate assembler.
44
55An assembler is itself an executable program that translates assembly language into an object module. In most cases the object modules are passed to a linker which then produces an executable program, although in some there are additional stages (code signing for secure operating systems, conversion to a binary for embedded systems and so on).
66
77## The ABI
88
99The interface between an executable program and the underlying operating system is referred to as the Application Binary Interface or ABI. This includes the CPU's operating mode (e.g. whether word and address sizes default to 32 or 64 bits), operand alignment, function calling conventions, system call numbers, and a selection of constants (e.g. file open modes) and structures (e.g. as returned by the stat() function). It is also usually considered to include the format of the object modules, executable and library files.
1010
1111Obviously the ABI is grossly different between operating systems: in general a program compiled for Windows will not run on Linux and vice versa. In addition, however, there is a significant amount of variation between different "flavours" of related operating systems, for example not only are the system call numbers different between SPARC Solaris and SPARC Linux but they are different between SPARC Linux and x86 Linux.
1212
1313## Purpose of this note
1414
1515In most cases FPC uses the GNU assembler ("as" or "gas") as its backend. However, the assembly language syntax expected by this is different for each target CPU, sections below give examples of this. The original incentive for this was because the author (MarkMLl) found that he needed to write an assembler reader for the MIPS processor, and that there was no straightforward comparison of existing formats on which he could base new code.
1616
1717In addition, in some cases the details of the assembly language format or the ABI specification are only available to users registered with the relevant manufacturer, where possible links to unofficial mirrors are given below for casual reference.
1818
1919## Assembler source formats
2020
2121Assembler source emitted by the compiler's code generator has to be (a subset of what is) acceptable to the assembler for the relevant target CPU. In addition, small portions of the RTL (e.g. prt0.as) are of necessity written in assembler, and some Pascal source files (e.g. syscall.inc) contain inline assembler which the compiler has to be able to parse before it is passed to the backend.
2222
2323The list of CPUs below is taken from the compiler as of late 2011. Some of these are no longer supported, or exist merely as minimal stubs.
2424
2525### Alpha
2626
2727This compiler exists only as a minimal stub.
2828
2929### ARM
3030
3131This fragment is from FpSysCall alias FPC_SYSCALL6 in FPC's ./rtl/linux/arm/syscall.inc:
3232
3333``` pascal
3434asm
3535 stmfd sp!,{r4,r5,r6}
3636 ldr r4,param4
3737 ldr r5,param5
3838 ldr r6,param6
3939 bl FPC_SYSCALL
4040 ldmfd sp!,{r4,r5,r6}
4141end;
4242```
4343
4444This fragment is from ret_from_fork in Linux's ./arch/arm/kernel/entry-common.S:
4545
46-```
46+```text
4747ENTRY(ret_from_fork)
4848 bl schedule_tail
4949 get_thread_info tsk
5050 ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing
5151 mov why, #1
5252 tst r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
5353 beq ret_slow_syscall
5454 mov r1, sp
5555 mov r0, #1 @ trace exit [IP = 1]
5656 bl syscall_trace
5757 b ret_slow_syscall
5858ENDPROC(ret_from_fork)
5959```
6060
6161Note that register names are r0, r1 etc. without a sigil, and that register assignment is right-to-left.
6262
6363### AVR
6464
6565This fragment is from part of fpc's startup code in /rtl/embedded/avr/start.inc:
6666
6767``` pascal
6868 _start:
6969 {$ifdef CPUAVR_16_REGS}
7070 clr r17
7171 {$else CPUAVR_16_REGS}
7272 clr r1
7373 {$endif CPUAVR_16_REGS}
7474
7575 // load stack pointer
7676 ldi r30,lo8(_stack_top)
7777 out 0x3d,r30
7878 ldi r30,hi8(_stack_top)
7979 out 0x3e,r30
8080
8181 // Initialize .data section
8282 ldi XL,lo8(_data)
8383 ldi XH,hi8(_data)
8484 ldi YH,hi8(_edata)
8585 ldi ZL,lo8(_etext)
8686 {$ifdef CPUAVR_16_REGS}
8787 ldi ZH,hi8(_etext)+(0x40) // program memory mapped to $4000 in data space
8888 {$else CPUAVR_16_REGS}
8989 ldi ZH,hi8(_etext)
9090 {$endif CPUAVR_16_REGS}
9191```
9292
9393Note that register names are r0, r1 etc. without a sigil, and that register assignment is right-to-left.
9494
9595### i386
9696
9797This fragment is from FpSysCall alias FPC_SYSCALL6 in FPC's ./rtl/linux/i386/syscall.inc:
9898
9999``` pascal
100100asm
101101 push %ebx
102102 push %edx
103103 push %esi
104104 push %edi
105105 push %ebp
106106 push %ecx
107107 cmp $0, sysenter_supported
108108 jne .LSysEnter
109109 movl %edx,%ebx // param1
110110 pop %ecx // param2
111111 movl param3,%edx // param3
112112 movl param4,%esi // param4
113113 movl param5,%edi // param5
114114 movl param6,%ebp // param6
115115 int $0x80
116116 jmp .LTail
117117 .LSysEnter:
118118 movl %edx,%ebx // param1
119119 pop %ecx // param2
120120 movl param3,%edx // param3
121121 movl param4,%esi // param4
122122 movl param5,%edi // param5
123123 movl param6,%ebp // param6
124124 call psysinfo
125125 .LTail:
126126 pop %ebp
127127 pop %edi
128128 pop %esi
129129 pop %edx
130130 pop %ebx
131131 cmpl $-4095,%eax
132132 jb .LSyscOK
133133 negl %eax
134134 call seterrno
135135 movl $-1,%eax
136136 .LSyscOK:
137137end;
138138```
139139
140140This fragment is from ret_from_fork in Linux's ./arch/x86/kernel/entry_32.S:
141141
142142``` pascal
143143ENTRY(ret_from_fork)
144144 CFI_STARTPROC
145145 pushl %eax
146146 CFI_ADJUST_CFA_OFFSET 4
147147 call schedule_tail
148148 GET_THREAD_INFO(%ebp)
149149 popl %eax
150150 CFI_ADJUST_CFA_OFFSET -4
151151 pushl $0x0202 # Reset kernel eflags
152152 CFI_ADJUST_CFA_OFFSET 4
153153 popfl
154154 CFI_ADJUST_CFA_OFFSET -4
155155 jmp syscall_exit
156156 CFI_ENDPROC
157157END(ret_from_fork)
158158```
159159
160160Note that register names are eax, ebx etc. with % as a mandatory sigil, and that register assignment is left-to-right.
161161
162162### IA-64
163163
164164This compiler exists only as a minimal stub.
165165
166166### M68K
167167
168168This compiler exists in FPC v1 and has lain dormant for a while but has since inclusion in FPC 2.x in the end of 2013.
169169
170170### MIPS
171171
172172This fragment is from FpSysCall alias FPC_SYSCALL6 in FPC's ./rtl/linux/mips/syscall.inc:
173173
174174``` pascal
175175asm
176176 sw $4,0($23)
177177 sw $5,-4($23)
178178 sw $6,-8($23)
179179 sw $7,-12($23)
180180 sw $8,-16($23)
181181 sw $9,-20($23)
182182 sw $10,-24($23)
183183 sw $11,-28($23)
184184 sw $12,-32($23)
185185 sw $13,-36($23)
186186 sw $14,-40($23)
187187 addiu $23,$23,-44
188188
189189 move $2,$4
190190 move $4,$5
191191 move $5,$6
192192 move $6,$7
193193 move $7,$8
194194 move $8,$9
195195 lw $9,0($fp)
196196
197197 subu $29,32
198198 sw $8, 16($29)
199199 sw $9, 20($29)
200200 syscall
201201 nop
202202 addiu $29,32
203203
204204 beq $7,$0,.LDone
205205 nop
206206 lui $8,%hi(fpc_threadvar_relocate_proc)
207207 addiu $8,%lo(fpc_threadvar_relocate_proc)
208208 lw $8,0($8)
209209 bne $8,$0,.LThreaded
210210 nop
211211 lui $4,%hi(Errno+4)
212212 addiu $4,%lo(Errno+4)
213213 sw $2,0($4)
214214 b .LFailed
215215 nop
216216.LThreaded:
217217 sw $2,-4($fp)#temp#sw $4
218218 lui $4,%hi(errno)
219219 addiu $4,$4,%lo(errno)
220220 jal $8
221221 nop
222222 lw $8,-4($fp)
223223 sw $8,0($2)
224224.LFailed:
225225 li $2,-1
226226.LDone:
227227
228228 addiu $23,$23,44
229229 lw $4,0($23)
230230 lw $5,-4($23)
231231 lw $6,-8($23)
232232 lw $7,-12($23)
233233 lw $8,-16($23)
234234 lw $9,-20($23)
235235 lw $10,-24($23)
236236 lw $11,-28($23)
237237 lw $12,-32($23)
238238 lw $13,-36($23)
239239 lw $14,-40($23)
240240
241241end;
242242```
243243
244244This fragment is from ret_from_fork in Linux's ./arch/mips/kernel/entry.S:
245245
246-```
246+```text
247247FEXPORT(ret_from_fork)
248248 jal schedule_tail # a0 = struct task_struct *prev
249249
250250FEXPORT(syscall_exit)
251251 local_irq_disable # make sure need_resched and
252252 # signals dont change between
253253 # sampling and return
254254 LONG_L a2, TI_FLAGS($28) # current->work
255255 li t0, _TIF_ALLWORK_MASK
256256 and t0, a2, t0
257257 bnez t0, syscall_exit_work
258258
259259FEXPORT(restore_all) # restore full frame
260260 .set noat
261261 RESTORE_TEMP
262262 RESTORE_AT
263263 RESTORE_STATIC
264264FEXPORT(restore_partial) # restore partial frame
265265 RESTORE_SOME
266266 RESTORE_SP_AND_RET
267267 .set at
268268```
269269
270270Note that register names are 0, 1 etc. with \$ as a mandatory sigil, and that register assignment is right-to-left; versions of GNU as from 2.18 onwards also support symbolic register names a0, a1 etc. There is a delay slot after branch etc. instructions.
271271
272272### PowerPC
273273
274274This fragment is from FpSysCall alias FPC_SYSCALL6 in FPC's ./rtl/linux/powerpc/syscall.inc:
275275
276276``` pascal
277277asm
278278 mr r0,r3
279279 mr r3,r4
280280 mr r4,r5
281281 mr r5,r6
282282 mr r6,r7
283283 mr r7,r8
284284 mr r8,r9
285285 sc
286286 bns .LDone
287287 lis r10,(fpc_threadvar_relocate_proc)@ha
288288 lwz r10,(fpc_threadvar_relocate_proc)@l(r10)
289289 cmpwi r10,0
290290 bne .LThreaded
291291 lis r4,(Errno+4)@ha
292292 stw r3,(Errno+4)@l(r4)
293293 b .LFailed
294294.LThreaded:
295295 stw r3,temp
296296 mflr r3
297297 mtctr r10
298298 lis r4,(errno)@ha
299299 stw r3,retaddress
300300 lwz r3,(errno)@l(r4)
301301 bctrl
302302 lwz r4,temp
303303 lwz r5,retaddress
304304 stw r4,0(r3)
305305 mtlr r5
306306.LFailed:
307307 li r3,-1
308308.LDone:
309309end;
310310```
311311
312312This fragment is from ret_from_fork in Linux's ./arch/powerpc/kernel/entry_32.S:
313313
314-```
314+```text
315315ret_from_syscall:
316316 mr r6,r3
317317 rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
318318 /* disable interrupts so current_thread_info()->flags can't change */
319319 LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
320320 /* Note: We don't bother telling lockdep about it */
321321 SYNC
322322 MTMSRD(r10)
323323 lwz r9,TI_FLAGS(r12)
324324 li r8,-_LAST_ERRNO
325325 andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
326326 bne- syscall_exit_work
327327 cmplw 0,r3,r8
328328 blt+ syscall_exit_cont
329329 lwz r11,_CCR(r1) /* Load CR */
330330 neg r3,r3
331331 oris r11,r11,0x1000 /* Set SO bit in CR */
332332 stw r11,_CCR(r1)
333333syscall_exit_cont:
334334 lwz r8,_MSR(r1)
335335BEGIN_FTR_SECTION
336336 lwarx r7,0,r1
337337END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
338338 stwcx. r0,0,r1 /* to clear the reservation */
339339 lwz r4,_LINK(r1)
340340 lwz r5,_CCR(r1)
341341 mtlr r4
342342 mtcr r5
343343 lwz r7,_NIP(r1)
344344 FIX_SRR1(r8, r0)
345345 lwz r2,GPR2(r1)
346346 lwz r1,GPR1(r1)
347347 mtspr SPRN_SRR0,r7
348348 mtspr SPRN_SRR1,r8
349349 SYNC
350350 RFI
351351
35235266: li r3,-ENOSYS
353353 b ret_from_syscall
354354
355355ret_from_fork:
356356 REST_NVGPRS(r1)
357357 bl schedule_tail
358358 li r3,0
359359 b ret_from_syscall
360360```
361361
362362Note that register names are r0, r1 etc. without a sigil, and that register assignment is right-to-left.
363363
364364### PowerPC-64
365365
366366Similar to PowerPC above.
367367
368368### SPARC
369369
370370This fragment is from FpSysCall alias FPC_SYSCALL6 in FPC's ./rtl/linux/sparc/syscall.inc:
371371
372372``` pascal
373373asm
374374 mov %i0,%g1
375375 mov %i1,%o0
376376 mov %i2,%o1
377377 mov %i3,%o2
378378 mov %i4,%o3
379379 ld [%i6+92],%o5
380380 mov %i5,%o4
381381 ta 0x10
382382 bcc .LSyscOK
383383 nop
384384 mov %o0,%l0
385385 sethi %hi(fpc_threadvar_relocate_proc),%o2
386386 or %o2,%lo(fpc_threadvar_relocate_proc),%o2
387387 ld [%o2],%o3
388388 subcc %o3,%g0,%g0
389389 bne .LThread
390390 nop
391391 sethi %hi(Errno+4),%o0
392392 ba .LNoThread
393393 or %o0,%lo(Errno+4),%o0
394394.LThread:
395395 sethi %hi(Errno),%o0
396396 or %o0,%lo(Errno),%o0
397397 call %o3
398398 ld [%o0],%o0
399399.LNoThread:
400400 st %l0,[%o0]
401401 mov -1,%o0
402402.LSyscOK:
403403 mov %o0,%i0
404404end;
405405```
406406
407407This fragment is from ret_from_fork in Linux's ./arch/sparc/kernel/entry.S:
408408
409-```
409+```text
410410linux_fast_syscall:
411411 andn %l7, 3, %l7
412412 mov %i0, %o0
413413 mov %i1, %o1
414414 mov %i2, %o2
415415 jmpl %l7 + %g0, %g0
416416 mov %i3, %o3
417417
418418linux_syscall_trace:
419419 add %sp, STACKFRAME_SZ, %o0
420420 call syscall_trace
421421 mov 0, %o1
422422 cmp %o0, 0
423423 bne 3f
424424 mov -ENOSYS, %o0
425425 mov %i0, %o0
426426 mov %i1, %o1
427427 mov %i2, %o2
428428 mov %i3, %o3
429429 b 2f
430430 mov %i4, %o4
431431
432432 .globl ret_from_fork
433433ret_from_fork:
434434 call schedule_tail
435435 mov %g3, %o0
436436 b ret_sys_call
437437 ld [%sp + STACKFRAME_SZ + PT_I0], %o0
438438
439439 /* Linux native system calls enter here... */
440440 .align 4
441441 .globl linux_sparc_syscall
442442linux_sparc_syscall:
443443 sethi %hi(PSR_SYSCALL), %l4
444444 or %l0, %l4, %l0
445445 /* Direct access to user regs, must faster. */
446446 cmp %g1, NR_SYSCALLS
447447 bgeu linux_sparc_ni_syscall
448448 sll %g1, 2, %l4
449449 ld [%l7 + %l4], %l7
450450 andcc %l7, 1, %g0
451451 bne linux_fast_syscall
452452 /* Just do first insn from SAVE_ALL in the delay slot */
453453```
454454
455455Note that register names are i0, i1 etc. with % as a mandatory sigil, and that register assignment is left-to-right. Registers are windowed, and there is a delay slot after branch etc. instructions.
456456
457457### VIS
458458
459459This compiler exists only as a minimal stub.
460460
461461### x86
462462
463463Refer to i386 above.
464464
465465### x86-64
466466
467467This fragment is from FpSysCall alias FPC_SYSCALL6 in FPC's ./rtl/linux/x86_64/syscall.inc:
468468
469469``` pascal
470470asm
471471 movq sysnr, %rax { Syscall number -> rax. }
472472 movq param1, %rdi { shift arg1 - arg5. }
473473 movq param2, %rsi
474474 movq param3, %rdx
475475 movq param4, %r10
476476 movq param5, %r8
477477 movq param6, %r9
478478 syscall { Do the system call. }
479479 cmpq $-4095, %rax { Check %rax for error. }
480480 jnae .LSyscOK { Jump to error handler if error. }
481481 negq %rax
482482 movq %rax,%rdx
483483 movq fpc_threadvar_relocate_proc,%rax
484484 leaq Errno,%r11
485485 testq %rax,%rax
486486 jne .LThread
487487 movl %edx,8(%r11)
488488 jmp .LNoThread
489489.LThread:
490490 pushq %rdx
491491 movq (%r11),%rdi
492492 call *%rax
493493 popq %rdx
494494 movl %edx,(%rax)
495495.LNoThread:
496496 movq $-1,%rax
497497.LSyscOK:
498498end;
499499```
500500
501501This fragment is from ret_from_fork in Linux's ./arch/x86/kernel/entry_64.S:
502502
503503``` pascal
504504ENTRY(ret_from_fork)
505505 DEFAULT_FRAME
506506
507507 LOCK ; btr $TIF_FORK,TI_flags(%r8)
508508
509509 push kernel_eflags(%rip)
510510 CFI_ADJUST_CFA_OFFSET 8
511511 popf # reset kernel eflags
512512 CFI_ADJUST_CFA_OFFSET -8
513513
514514 call schedule_tail # rdi: 'prev' task parameter
515515
516516 GET_THREAD_INFO(%rcx)
517517
518518 RESTORE_REST
519519
520520 testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread?
521521 je int_ret_from_sys_call
522522
523523 testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET
524524 jnz int_ret_from_sys_call
525525
526526 RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
527527 jmp ret_from_sys_call # go to the SYSRET fastpath
528528
529529 CFI_ENDPROC
530530END(ret_from_fork)
531531```
532532
533533Note that register names are rax, rbx etc. with % as a mandatory sigil, and that register assignment is left-to-right.
534534
535535### zSeries (S/390)
536536
537537As of early 2012, IBM's [[ZSeries|zSeries]] (formerly System/390) is not supported by the compiler, refer to [[ZSeries/Part 1]] for the current implementation status. Note that Linux 2.6 probably won't run on anything older than an S/390 G5.
538538
539539#### For the GNU assembler (gas):
540540
541541This fragment is from ret_from_fork in Linux's ./arch/s390/kernel/entry.S:
542542
543-```
543+```text
544544#define BASED(name) name-system_call(%r13)
545545
546546 .globl ret_from_fork
547547ret_from_fork:
548548 l %r13,__LC_SVC_NEW_PSW+4
549549 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
550550 tm SP_PSW+1(%r15),0x01 # forking a kernel thread ?
551551 bo BASED(0f)
552552 st %r15,SP_R15(%r15) # store stack pointer for new kthread
5535530: l %r1,BASED(.Lschedtail)
554554 basr %r14,%r1
555555 TRACE_IRQS_ON
556556 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
557557 b BASED(sysc_tracenogo)
558558
559559sysc_tracenogo:
560560 tm __TI_flags+2(%r9),_TIF_SYSCALL
561561 bz BASED(sysc_return)
562562 l %r1,BASED(.Ltrace_exit)
563563 la %r2,SP_PTREGS(%r15) # load pt_regs
564564 la %r14,BASED(sysc_return)
565565 br %r1
566566```
567567
568568Note that register names are r0, r1 etc. with % as a mandatory sigil. Older assemblers (below) arranged the operands as ordered in the binary opcode (i.e. register assignment order varies by operation), this might have changed for the GNU assembler resulting in obvious compatibility problems.
569569
570570#### For the IBM assembler:
571571
572572For the purpose of comparison and with minimal comment, here are "Hello, World!" programs compiled with GCC for different targets.
573573
574574``` pascal
575575GCCMVS on MUSIC/SP hosted by Sim/390 using the command
576576
577577gccmvs_v30 -S -o hello.asm ... hello.c
578578
579579generates this:
580580
581581LC0 EQU *
582582 DC C'Hello, MUSIC/SP!'
583583 DC X'15'
584584 DC X'0'
585585 DS 0F
586586 EXTRN @@CRT0
587587* Function main prologue
588588MAIN PDPPRLG CINDEX=0,FRAME=92,BASER=12,ENTRY=YES
589589 B FEN0
590590 LTORG
591591FEN0 EQU *
592592 DROP 12
593593 BALR 12,0
594594 USING *,12
595595PG0 EQU *
596596 LR 11,1
597597 L 10,=A(PGT0)
598598* Function main code
599599 MVC 88(4,13),=A(LC0)
600600 LA 1,88(,13)
601601 L 15,=V(PRINTF)
602602 BALR 14,15
603603 SLR 2,2
604604 LR 15,2
605605```
606606
607607In the example above, note that registers are identified numerically (e.g. BALR 12,0); it is common to load a macro package which introduces a leading R as a sigil (i.e. BALR R12,R0). The operands are ordered as in the binary opcode (i.e. register assignment order varies by operation), this might have changed for the GNU assembler (see section above) resulting in obvious compatibility problems.
608608
609609``` pascal
610610GCC on zSeries Linux hosted by Hercules using the command
611611
612612gcc -S -o hello.asm hello.c
613613
614614apparently assuming -march=g5, generates this:
615615
616616.LC0:
617617 .string "Hello, Linux!"
618618.text
619619 .align 4
620620.globl main
621621 .type main, @function
622622main:
623623.LFB2:
624624 stm %r11,%r15,44(%r15)
625625.LCFI0:
626626 basr %r13,0
627627.L3:
628628 ahi %r15,-96
629629.LCFI1:
630630 lr %r11,%r15
631631.LCFI2:
632632 l %r1,.L4-.L3(%r13)
633633 lr %r2,%r1
634634 l %r1,.L5-.L3(%r13)
635635 basr %r14,%r1
636636 lhi %r1,0
637637 lr %r2,%r1
638638 l %r4,152(%r11)
639639 lm %r11,%r15,140(%r11)
640640 br %r4
641641 .align 4
642642.L5:
643643 .long puts
644644.L4:
645645 .long .LC0
646646
647647I think that's still effectively generating code similar to traditional
648648assembler's "using".
649649```
650650
651651``` pascal
652652With the explicit instruction to use a later CPU:
653653
654654gcc -march=z900 -S -o hello.asm hello.c
655655
656656it generates this:
657657
658658.LC0:
659659 .string "Hello, Linux!"
660660.text
661661 .align 4
662662.globl main
663663 .type main, @function
664664main:
665665.LFB2:
666666 stm %r11,%r15,44(%r15)
667667.LCFI0:
668668 ahi %r15,-96
669669.LCFI1:
670670 lr %r11,%r15
671671.LCFI2:
672672 larl %r2,.LC0
673673 brasl %r14,puts
674674 lhi %r1,0
675675 lr %r2,%r1
676676 l %r4,152(%r11)
677677 lm %r11,%r15,140(%r11)
678678 br %r4
679679
680680If I'm reading that correctly, it's referring to the string directly
681681without using a register.
682682```
683683
684684## ABI references
685685
686686The list of CPUs etc. is based on those found in the compiler (see above).
687687
688688### Alpha
689689
690690### ARM
691691
692692### AVR
693693
694694Currently only the embedded target is supported by FPC. The compiler follows the register layout [1](https://gcc.gnu.org/wiki/avr-gcc#Register_Layout), frame layout [2](https://gcc.gnu.org/wiki/avr-gcc#Frame_Layout) and calling convention [3](https://gcc.gnu.org/wiki/avr-gcc#Calling_Convention) of the avr-gcc ABI.
695695
696696### i386
697697
698698### IA-64
699699
700700### M68K
701701
702702### MIPS
703703
704704MIPS has several kinds of ABI, including O32, EABI, n32, n64, nowadays the de facto one should be O32. Some ABI document for MIPS O32 ABI can be found in the internet, unfortunately due to the copyright limit, we cannot provide it here. However, this page [4](http://www.linux-mips.org/wiki/MIPSABIHistory) has some useful links.
705705
706706### PowerPC
707707
708708### PowerPC-64
709709
710710### SPARC
711711
712712SPARC is an open architecture. All design documents are freely available (no signup required) from sparc.org and opensparc.net. sparc.org has documents on the 32 bit SPARC version V8 and the 64 bit SPARC version V9. Earlier versions of the architecture, specifically V7 are available on the net (search for Solbourne).
713713
714714You can download the SPARC V8 Architecture Manual here: [5](http://sparc.org/standards/V8.pdf) The SPARC V8 ABI for UNIX is here: [6](http://sparc.org/standards/psABI3rd.pdf)
715715
716716You can download the SPARC V9 Architecture Manual here: [7](http://sparc.org/standards/SPARCV9.pdf) The SPARC V9 ABI for UNIX is here: [8](http://sparc.org/standards/SCD.2.4.1.ps.Z) Newer versions than V9 are available on opensparc.net.
717717
718718### VIS
719719
720720### x86
721721
722722### x86-64
723723
724724### zSeries (S/390)
725725
726726The classic IBM operating systems, particularly when running on older hardware (i.e. preceding the S/390 G5) historically adopt a programming style which passes function parameters in registers and blocks of memory rather than using a stack.
727727
728728For Linux on a 32-bit S/390, "The first 5 integer (char, short, int, long, long long) and pointer parameters are passed in registers R2, R3, R4, R5 and R6. ... long long parameters are passed in register pairs. Structures of 1, 2, 4 or 8 bytes are passed as integers. ... the first 2 floating point parameters are passed in F0 and F2. ... All other parameters are passed on the stack. If the return value is not an integer, pointer, float, double or 1, 2, 4 or 9-byte structure, a "hidden" parameter in R2 will contain the address of the return area." [9](http://linuxvm.org/present/SHARE99/S8139db.pdf)
729729
730730## Other resources
731731
732732As a general point, there's some useful thoughts on binary disassembly at <http://chdk.wikia.com/wiki/GPL_Disassembling> for situations where IDA or equivalent aren't available.
733733
734734---
735735*From the Free Pascal wiki, page "Assembler and ABI Resources", as it stood on 2022-06-18 after a change by Alextp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
736736Category: FPC internals

Back to history