// We look at the ARMv8 CPU instruction set, used by Apple Silicon M1 and subsequent Aarch64 chips. sergey@snowball armv8 % cat hello-loop.c #include int main() { int i = 10; while( i >= 0 ){ i = i - 1; puts( "Hello" ); } return 42; } sergey@snowball armv8 % gcc -v Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1 Apple clang version 13.0.0 (clang-1300.0.29.30) Target: arm64-apple-darwin20.6.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin sergey@snowball armv8 % gcc -Wall -o h hello-loop.c // Mach-O is a cousin of ELF and PE executable and linkable file formats, used by Linux / and Windows respectively. sergey@snowball armv8 % file h h: Mach-O 64-bit arm64 executable, flags: sergey@snowball armv8 % lldb ./h (lldb) target create "./h" Current executable set to '/Users/user/cs59/armv8/h' (arm64). (lldb) disas -n main h`main: h[0x100003f34] <+0>: sub sp, sp, #0x20 ; =0x20 h[0x100003f38] <+4>: stp x29, x30, [sp, #0x10] h[0x100003f3c] <+8>: add x29, sp, #0x10 ; =0x10 h[0x100003f40] <+12>: stur wzr, [x29, #-0x4] h[0x100003f44] <+16>: mov w8, #0xa h[0x100003f48] <+20>: str w8, [sp, #0x8] h[0x100003f4c] <+24>: ldr w8, [sp, #0x8] h[0x100003f50] <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> h[0x100003f54] <+32>: ldr w8, [sp, #0x8] h[0x100003f58] <+36>: subs w8, w8, #0x1 ; =0x1 h[0x100003f5c] <+40>: str w8, [sp, #0x8] h[0x100003f60] <+44>: adrp x0, 0 h[0x100003f64] <+48>: add x0, x0, #0xfb0 ; =0xfb0 h[0x100003f68] <+52>: bl 0x100003f80 ; symbol stub for: puts h[0x100003f6c] <+56>: b 0x100003f4c ; <+24> h[0x100003f70] <+60>: mov w0, #0x2a h[0x100003f74] <+64>: ldp x29, x30, [sp, #0x10] h[0x100003f78] <+68>: add sp, sp, #0x20 ; =0x20 h[0x100003f7c] <+72>: ret // ARM instructions have a uniform encoded length of 4 bytes, unlike x86 variable-length // instructions. (lldb) disas -b -n main h`main: h[0x100003f34] <+0>: 0xd10083ff sub sp, sp, #0x20 ; =0x20 h[0x100003f38] <+4>: 0xa9017bfd stp x29, x30, [sp, #0x10] h[0x100003f3c] <+8>: 0x910043fd add x29, sp, #0x10 ; =0x10 h[0x100003f40] <+12>: 0xb81fc3bf stur wzr, [x29, #-0x4] h[0x100003f44] <+16>: 0x52800148 mov w8, #0xa h[0x100003f48] <+20>: 0xb9000be8 str w8, [sp, #0x8] h[0x100003f4c] <+24>: 0xb9400be8 ldr w8, [sp, #0x8] h[0x100003f50] <+28>: 0x37f80108 tbnz w8, #0x1f, 0x100003f70 ; <+60> h[0x100003f54] <+32>: 0xb9400be8 ldr w8, [sp, #0x8] h[0x100003f58] <+36>: 0x71000508 subs w8, w8, #0x1 ; =0x1 h[0x100003f5c] <+40>: 0xb9000be8 str w8, [sp, #0x8] h[0x100003f60] <+44>: 0x90000000 adrp x0, 0 h[0x100003f64] <+48>: 0x913ec000 add x0, x0, #0xfb0 ; =0xfb0 h[0x100003f68] <+52>: 0x94000006 bl 0x100003f80 ; symbol stub for: puts h[0x100003f6c] <+56>: 0x17fffff8 b 0x100003f4c ; <+24> h[0x100003f70] <+60>: 0x52800540 mov w0, #0x2a h[0x100003f74] <+64>: 0xa9417bfd ldp x29, x30, [sp, #0x10] h[0x100003f78] <+68>: 0x910083ff add sp, sp, #0x20 ; =0x20 h[0x100003f7c] <+72>: 0xd65f03c0 ret (lldb) b main Breakpoint 1: where = h`main, address = 0x0000000100003f34 (lldb) r Process 17477 launched: '/Users/user/cs59/armv8/h' (arm64) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000100003f34 h`main h`main: -> 0x100003f34 <+0>: sub sp, sp, #0x20 ; =0x20 0x100003f38 <+4>: stp x29, x30, [sp, #0x10] 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 0x100003f40 <+12>: stur wzr, [x29, #-0x4] Target 0: (h) stopped. // The three top instructions make the stack frame for main(): low addr high addr SP SP+0x8 SP+0xC SP+0x10 SP+0x18 SP+0x20 | | | | | | v v v v v v +--------+--------+------------+------------+-----------------+-----------------+ | unused (pad) | local "i" | 0-ed,unused| saved X29 | saved X30 | | 8 bytes | 4 bytes | 4 bytes | (old FP) | (LR / ret) | +-----------------+------------+------------+-----------------+-----------------+ ^ X29 (FP) points here after 0x100003f3c (lldb) reg r $sp sp = 0x000000016fdff470 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f38 h`main + 4 h`main: -> 0x100003f38 <+4>: stp x29, x30, [sp, #0x10] 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa Target 0: (h) stopped. // ..and now the notional frame is created: (lldb) reg r $sp sp = 0x000000016fdff450 // FP and LR (x29 and x30) will be saved next: (lldb) x/10gx $sp 0x16fdff450: 0x0000000000000000 0x0000000000000000 0x16fdff460: 0x000000016fdff480 0xc902000100011038 // <-- saved FP & LR will go here 0x16fdff470: 0x0000000197c7d430 0x0000000000000000 0x16fdff480: 0x0000000000000000 0x0000000000000000 0x16fdff490: 0x0000000000000000 0x0000000100000000 (lldb) reg r $x29 $x30 fp = 0x000000016fdff480 lr = 0x0000000197c7d430 libdyld.dylib`start + 4 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f3c h`main + 8 h`main: -> 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] Target 0: (h) stopped. (lldb) x/10gx $sp 0x16fdff450: 0x0000000000000000 0x0000000000000000 0x16fdff460: 0x000000016fdff480 0x0000000197c7d430 // <--- ..and they did 0x16fdff470: 0x0000000197c7d430 0x0000000000000000 0x16fdff480: 0x0000000000000000 0x0000000000000000 0x16fdff490: 0x0000000000000000 0x0000000100000000 // The FP for this frame will be set now: (lldb) dis h`main: 0x100003f34 <+0>: sub sp, sp, #0x20 ; =0x20 0x100003f38 <+4>: stp x29, x30, [sp, #0x10] -> 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 0x100003f7c <+72>: ret (lldb) reg r $x29 $x30 fp = 0x000000016fdff480 lr = 0x0000000197c7d430 libdyld.dylib`start + 4 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f40 h`main + 12 h`main: -> 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] 0x100003f4c <+24>: ldr w8, [sp, #0x8] Target 0: (h) stopped. // Now FP is pointing to its intended place in the frame. Note that since SP // doesn't move during the function, the compiler keeps addressing locals // off of SP, and ignored FP. That would not be the case if the function // needed to save more things on the stack, which would move SP but keep FP put. (lldb) reg r $x29 $x30 fp = 0x000000016fdff460 lr = 0x0000000197c7d430 libdyld.dylib`start + 4 (lldb) reg r $sp sp = 0x000000016fdff450 // I haven't found a reason for zeroing out these 4 bytes. Claude suggests // these are for storing a "result" variable, but I doubt it. The local variable // "i" could live there, but I think the compiler prefers to have it at // the 8-byte alignment. (lldb) dis h`main: 0x100003f34 <+0>: sub sp, sp, #0x20 ; =0x20 0x100003f38 <+4>: stp x29, x30, [sp, #0x10] 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 -> 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] // <<-- behold: i = 10 0x100003f4c <+24>: ldr w8, [sp, #0x8] // this instruction is redundant and can be optimized away, but I didn't ask for optimization yet 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> // check for i >= 0, jump to the end of the function if the sign bit (bit 31) of w8 is set 0x100003f54 <+32>: ldr w8, [sp, #0x8] // ARM can only do arithmetic in registers 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 // i = i-1 0x100003f5c <+40>: str w8, [sp, #0x8] // .. store the new value of i 0x100003f60 <+44>: adrp x0, 0 // data addresses like the pointer to "Hello" // must be built up by two instructions // due to ARM's fixed-length instruction encoding 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> // jump back to the top of while() 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 0x100003f7c <+72>: ret (lldb) dis -b h`main: 0x100003f34 <+0>: 0xd10083ff sub sp, sp, #0x20 ; =0x20 0x100003f38 <+4>: 0xa9017bfd stp x29, x30, [sp, #0x10] 0x100003f3c <+8>: 0x910043fd add x29, sp, #0x10 ; =0x10 -> 0x100003f40 <+12>: 0xb81fc3bf stur wzr, [x29, #-0x4] 0x100003f44 <+16>: 0x52800148 mov w8, #0xa 0x100003f48 <+20>: 0xb9000be8 str w8, [sp, #0x8] 0x100003f4c <+24>: 0xb9400be8 ldr w8, [sp, #0x8] 0x100003f50 <+28>: 0x37f80108 tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: 0xb9400be8 ldr w8, [sp, #0x8] 0x100003f58 <+36>: 0x71000508 subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: 0xb9000be8 str w8, [sp, #0x8] 0x100003f60 <+44>: 0x90000000 adrp x0, 0 0x100003f64 <+48>: 0x913ec000 add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: 0x94000006 bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: 0x17fffff8 b 0x100003f4c ; <+24> 0x100003f70 <+60>: 0x52800540 mov w0, #0x2a 0x100003f74 <+64>: 0xa9417bfd ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: 0x910083ff add sp, sp, #0x20 ; =0x20 0x100003f7c <+72>: 0xd65f03c0 ret (lldb) reg r $sp sp = 0x000000016fdff450 // Let's see the stack before "i" is saved: (lldb) x/10gx $sp 0x16fdff450: 0x0000000000000000 0x0000000000000000 0x16fdff460: 0x000000016fdff480 0x0000000197c7d430 0x16fdff470: 0x0000000197c7d430 0x0000000000000000 0x16fdff480: 0x0000000000000000 0x0000000000000000 0x16fdff490: 0x0000000000000000 0x0000000100000000 (lldb) x/10wx $sp 0x16fdff450: 0x00000000 0x00000000 0x00000000 0x00000000 0x16fdff460: 0x6fdff480 0x00000001 0x97c7d430 0x00000001 0x16fdff470: 0x97c7d430 0x00000001 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f44 h`main + 16 h`main: -> 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> Target 0: (h) stopped. (lldb) reg r $w8 w8 = 0x3f9500f0 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f48 h`main + 20 h`main: -> 0x100003f48 <+20>: str w8, [sp, #0x8] 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] Target 0: (h) stopped. (lldb) reg r $w8 w8 = 0x0000000a // ... and after (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f4c h`main + 24 h`main: -> 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 Target 0: (h) stopped. (lldb) x/10gx $sp 0x16fdff450: 0x0000000000000000 0x000000000000000a <<--- "i" 0x16fdff460: 0x000000016fdff480 0x0000000197c7d430 0x16fdff470: 0x0000000197c7d430 0x0000000000000000 0x16fdff480: 0x0000000000000000 0x0000000000000000 0x16fdff490: 0x0000000000000000 0x0000000100000000 (lldb) x/10wx $sp 0x16fdff450: 0x00000000 0x00000000 0x0000000a 0x00000000 <<-- "i" at exactly SP+8 0x16fdff460: 0x6fdff480 0x00000001 0x97c7d430 0x00000001 0x16fdff470: 0x97c7d430 0x00000001 // Integers are little-endian: (lldb) x/16bx $sp 0x16fdff450: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x16fdff458: 0x0a 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ^^^^^^^^^^^^^^^^^^^ "i" (lldb) dis h`main: 0x100003f34 <+0>: sub sp, sp, #0x20 ; =0x20 0x100003f38 <+4>: stp x29, x30, [sp, #0x10] 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] -> 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 0x100003f7c <+72>: ret // We test "i >= 0" and pass: (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f50 h`main + 28 h`main: -> 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] Target 0: (h) stopped. // And now we do "i = i - 1": (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f54 h`main + 32 h`main: -> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f58 h`main + 36 h`main: -> 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 Target 0: (h) stopped. (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f5c h`main + 40 h`main: -> 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts Target 0: (h) stopped. // subtraction in register and storage back to the stack frame: (lldb) reg r $w8 w8 = 0x00000009 // Now we load the address of "Hello": (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f60 h`main + 44 h`main: -> 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> Target 0: (h) stopped. (lldb) x/10gx $sp 0x16fdff450: 0x0000000000000000 0x0000000000000009 // i is 9 now 0x16fdff460: 0x000000016fdff480 0x0000000197c7d430 0x16fdff470: 0x0000000197c7d430 0x0000000000000000 0x16fdff480: 0x0000000000000000 0x0000000000000000 0x16fdff490: 0x0000000000000000 0x0000000100000000 (lldb) reg r $x0 x0 = 0x0000000000000001 // Loading a data address, such as the pointer to the string "Hello\0", needs two // instructions, one for the 4K page address, another for the offset within that page: (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f64 h`main + 48 h`main: -> 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a Target 0: (h) stopped. // Page top: (lldb) reg r $x0 x0 = 0x0000000100003000 h`_mh_execute_header + 12288 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f68 h`main + 52 h`main: -> 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] Target 0: (h) stopped. // The address of "Hello", good to go as the first and only argument to puts(), // passed via x0 as per Aarch64 calling convention: (lldb) reg r $x0 x0 = 0x0000000100003fb0 "Hello" // <-- LLDB helpfully shows what's there at that address (lldb) x/10bx $x0 0x100003fb0: 0x48 0x65 0x6c 0x6c 0x6f 0x00 0x00 0x00 0x100003fb8: 0x01 0x00 // We are now jumping to the "stub" for puts(). Standard library functions are dynamically // linked, which means the compiler only provides the stubs for them in the current // compilation unit. When called, these stubs will call out to the dynamic linker (DYLD), // which will load the right precompiled library and point the stub to it. // Let's follow these jumps the first time puts() stub is called: (lldb) x/12i 0x100003f80 0x100003f80: 0xd503201f nop 0x100003f84: 0x580203f0 ldr x16, #0x407c ; (void *)0x0000000100003fa4 0x100003f88: 0xd61f0200 br x16 0x100003f8c: 0x100203f1 adr x17, #0x407c ; _dyld_private 0x100003f90: 0xd503201f nop 0x100003f94: 0xa9bf47f0 stp x16, x17, [sp, #-0x10]! 0x100003f98: 0xd503201f nop 0x100003f9c: 0x58000330 ldr x16, #0x64 ; (void *)0x0000000197c7bbd8: dyld_stub_binder 0x100003fa0: 0xd61f0200 br x16 0x100003fa4: 0x18000050 ldr w16, 0x100003fac 0x100003fa8: 0x17fffff9 b 0x100003f8c 0x100003fac: 0x00000000 udf #0x0 // <<-- this is 4 bytes of data, read by LDR at 0x100003fa4 . ARM does intersperse data and code (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f80 h`puts h`puts: 0x100003f80 <+0>: nop 0x100003f84 <+4>: ldr x16, #0x407c ; (void *)0x0000000100003fa4 0x100003f88 <+8>: br x16 0x100003f8c: adr x17, #0x407c ; _dyld_private Target 0: (h) stopped. // Note that when puts() is done it will return to here: (lldb) reg r $x30 lr = 0x0000000100003f6c h`main + 56 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f84 h`puts + 4 h`puts: -> 0x100003f84 <+4>: ldr x16, #0x407c ; (void *)0x0000000100003fa4 0x100003f88 <+8>: br x16 0x100003f8c: adr x17, #0x407c ; _dyld_private 0x100003f90: nop Target 0: (h) stopped. // ..a few more steps into the stub and the dynamic loader: (lldb) reg r $x16 x16 = 0x0000000100003f34 h`main (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f88 h`puts + 8 h`puts: -> 0x100003f88 <+8>: br x16 0x100003f8c: adr x17, #0x407c ; _dyld_private 0x100003f90: nop 0x100003f94: stp x16, x17, [sp, #-0x10]! Target 0: (h) stopped. (lldb) reg r $x16 x16 = 0x0000000100003fa4 (lldb) x/1i 0x0000000100003fa4 0x100003fa4: 0x18000050 ldr w16, 0x100003fac (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003fa4 h -> 0x100003fa4: ldr w16, 0x100003fac 0x100003fa8: b 0x100003f8c 0x100003fac: udf #0x0 0x100003fb0: ldnp d8, d25, [x10, #-0x140] Target 0: (h) stopped. (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003fa8 h -> 0x100003fa8: b 0x100003f8c 0x100003fac: udf #0x0 0x100003fb0: ldnp d8, d25, [x10, #-0x140] 0x100003fb4: udf #0x6f Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f8c h 0x100003f8c: adr x17, #0x407c ; _dyld_private 0x100003f90: nop 0x100003f94: stp x16, x17, [sp, #-0x10]! 0x100003f98: nop Target 0: (h) stopped. (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f90 h -> 0x100003f90: nop 0x100003f94: stp x16, x17, [sp, #-0x10]! 0x100003f98: nop 0x100003f9c: ldr x16, #0x64 ; (void *)0x0000000197c7bbd8: dyld_stub_binder Target 0: (h) stopped. // We let the dynamic loader continue, and will catch the execution after puts() returns: (lldb) dis -n main h`main: 0x100003f34 <+0>: sub sp, sp, #0x20 ; =0x20 0x100003f38 <+4>: stp x29, x30, [sp, #0x10] 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 0x100003f7c <+72>: ret (lldb) b 0x100003f6c Breakpoint 2: where = h`main + 56, address = 0x0000000100003f6c (lldb) c Process 17477 resuming Hello Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x0000000100003f6c h`main + 56 h`main: -> 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 Target 0: (h) stopped. // We go back thought the loop, but puts() will now go straight to its library // implementation: (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f4c h`main + 24 h`main: -> 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 Target 0: (h) stopped. (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f50 h`main + 28 h`main: -> 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] Target 0: (h) stopped. (lldb) reg r $w8 w8 = 0x00000009 (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f54 h`main + 32 h`main: -> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f58 h`main + 36 h`main: -> 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f5c h`main + 40 h`main: -> 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f60 h`main + 44 h`main: -> 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f64 h`main + 48 h`main: -> 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f68 h`main + 52 h`main: -> 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f80 h`puts h`puts: 0x100003f80 <+0>: nop 0x100003f84 <+4>: ldr x16, #0x407c ; (void *)0x0000000197b70004: puts 0x100003f88 <+8>: br x16 0x100003f8c: adr x17, #0x407c ; _dyld_private Target 0: (h) stopped. // We are now calling puts(), but look: the next jump will be straight to it: (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f84 h`puts + 4 h`puts: -> 0x100003f84 <+4>: ldr x16, #0x407c ; (void *)0x0000000197b70004: puts 0x100003f88 <+8>: br x16 0x100003f8c: adr x17, #0x407c ; _dyld_private 0x100003f90: nop Target 0: (h) stopped. (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f88 h`puts + 8 h`puts: -> 0x100003f88 <+8>: br x16 0x100003f8c: adr x17, #0x407c ; _dyld_private 0x100003f90: nop 0x100003f94: stp x16, x17, [sp, #-0x10]! Target 0: (h) stopped. // ..and we are now in the standard library puts() implementation: (lldb) Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000197b70004 libsystem_c.dylib`puts libsystem_c.dylib`puts: -> 0x197b70004 <+0>: pacibsp 0x197b70008 <+4>: sub sp, sp, #0x60 ; =0x60 0x197b7000c <+8>: stp x20, x19, [sp, #0x40] 0x197b70010 <+12>: stp x29, x30, [sp, #0x50] Target 0: (h) stopped. (lldb) c Process 17477 resuming Hello Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x0000000100003f6c h`main + 56 h`main: -> 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 Target 0: (h) stopped. (lldb) dis -n main h`main: 0x100003f34 <+0>: sub sp, sp, #0x20 ; =0x20 0x100003f38 <+4>: stp x29, x30, [sp, #0x10] 0x100003f3c <+8>: add x29, sp, #0x10 ; =0x10 0x100003f40 <+12>: stur wzr, [x29, #-0x4] 0x100003f44 <+16>: mov w8, #0xa 0x100003f48 <+20>: str w8, [sp, #0x8] 0x100003f4c <+24>: ldr w8, [sp, #0x8] 0x100003f50 <+28>: tbnz w8, #0x1f, 0x100003f70 ; <+60> 0x100003f54 <+32>: ldr w8, [sp, #0x8] 0x100003f58 <+36>: subs w8, w8, #0x1 ; =0x1 0x100003f5c <+40>: str w8, [sp, #0x8] 0x100003f60 <+44>: adrp x0, 0 0x100003f64 <+48>: add x0, x0, #0xfb0 ; =0xfb0 0x100003f68 <+52>: bl 0x100003f80 ; symbol stub for: puts -> 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 0x100003f7c <+72>: ret // We'll catch the function after the loop exits and it's time to return: (lldb) b 0x100003f78 Breakpoint 3: where = h`main + 68, address = 0x0000000100003f78 (lldb) c Process 17477 resuming Hello Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x0000000100003f6c h`main + 56 h`main: -> 0x100003f6c <+56>: b 0x100003f4c ; <+24> 0x100003f70 <+60>: mov w0, #0x2a 0x100003f74 <+64>: ldp x29, x30, [sp, #0x10] 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 Target 0: (h) stopped. (lldb) breakpoint Commands for operating on breakpoints (see 'help b' for shorthand.) Syntax: breakpoint [] The following subcommands are supported: clear -- Delete or disable breakpoints matching the specified source file and line. command -- Commands for adding, removing and listing LLDB commands executed when a breakpoint is hit. delete -- Delete the specified breakpoint(s). If no breakpoints are specified, delete them all. disable -- Disable the specified breakpoint(s) without deleting them. If none are specified, disable all breakpoints. enable -- Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them. list -- List some or all breakpoints at configurable levels of detail. modify -- Modify the options on a breakpoint or set of breakpoints in the executable. If no breakpoint is specified, acts on the last created breakpoint. With the exception of -e, -d and -i, passing an empty argument clears the modification. name -- Commands to manage name tags for breakpoints read -- Read and set the breakpoints previously saved to a file with "breakpoint write". set -- Sets a breakpoint or set of breakpoints in the executable. write -- Write the breakpoints listed to a file that can be read in with "breakpoint read". If given no arguments, writes all breakpoints. For more help on any particular subcommand, type 'help '. (lldb) breakpoint list Current breakpoints: 1: name = 'main', locations = 1, resolved = 1, hit count = 1 1.1: where = h`main, address = 0x0000000100003f34, resolved, hit count = 1 2: address = h[0x0000000100003f6c], locations = 1, resolved = 1, hit count = 3 2.1: where = h`main + 56, address = 0x0000000100003f6c, resolved, hit count = 3 3: address = h[0x0000000100003f78], locations = 1, resolved = 1, hit count = 0 3.1: where = h`main + 68, address = 0x0000000100003f78, resolved, hit count = 0 (lldb) break delete 2 1 breakpoints deleted; 0 breakpoint locations disabled. (lldb) breakpoint list Current breakpoints: 1: name = 'main', locations = 1, resolved = 1, hit count = 1 1.1: where = h`main, address = 0x0000000100003f34, resolved, hit count = 1 3: address = h[0x0000000100003f78], locations = 1, resolved = 1, hit count = 0 3.1: where = h`main + 68, address = 0x0000000100003f78, resolved, hit count = 0 (lldb) c Process 17477 resuming Hello Hello Hello Hello Hello Hello Hello Hello Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1 frame #0: 0x0000000100003f78 h`main + 68 h`main: -> 0x100003f78 <+68>: add sp, sp, #0x20 ; =0x20 0x100003f7c <+72>: ret h`puts: 0x100003f80 <+0>: nop 0x100003f84 <+4>: ldr x16, #0x407c ; (void *)0x0000000197b70004: puts Target 0: (h) stopped. // LR points to where main() must return: (lldb) reg r $x30 lr = 0x0000000197c7d430 libdyld.dylib`start + 4 // X0 holds the return value, as per ARM calling convention: (lldb) reg r $x0 x0 = 0x000000000000002a (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000100003f7c h`main + 72 h`main: -> 0x100003f7c <+72>: ret h`puts: 0x100003f80 <+0>: nop 0x100003f84 <+4>: ldr x16, #0x407c ; (void *)0x0000000197b70004: puts 0x100003f88 <+8>: br x16 Target 0: (h) stopped. // .. and we are now heading back to the shell, via exit() (lldb) si Process 17477 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into frame #0: 0x0000000197c7d430 libdyld.dylib`start + 4 libdyld.dylib`start: -> 0x197c7d430 <+4>: bl 0x197c9e410 ; symbol stub for: exit 0x197c7d434 <+8>: brk #0x3 libdyld.dylib`dyld3::kdebug_trace_dyld_marker: 0x197c7d438 <+0>: pacibsp 0x197c7d43c <+4>: stp x28, x27, [sp, #-0x60]! Target 0: (h) stopped. (lldb) reg r $x30 lr = 0x0000000197c7d430 libdyld.dylib`start + 4 // Oops, syntax: (lldb) x/10gx $sp - 0x20 error: memory read takes a start address expression with an optional end address expression. Expressions should be quoted if they contain spaces or other special characters. (lldb) x/10gx $sp-0x20 0x16fdff450: 0x0000000000000000 0x00000000ffffffff // <<-- note, "i" is now "-1" in 32-bit 2's complement integer encoding, 0xffffffff 0x16fdff460: 0x000000016fdff480 0x0000000197c7d430 0x16fdff470: 0x0000000197c7d430 0x0000000000000000 0x16fdff480: 0x0000000000000000 0x0000000000000000 0x16fdff490: 0x0000000000000000 0x0000000100000000 (lldb) ^D // Optimized compilation removes most of the compiler template logic that deals // with local variables and their storage, etc.: sergey@snowball armv8 % cat hello-loop.c #include int main() { int i = 10; while( i >= 0 ){ i = i - 1; puts( "Hello" ); } return 42; } // -O2 is the normal level of optimization: sergey@snowball armv8 % gcc -O2 -o h2 hello-loop.c // We see that the loop has been replaced with 11 calls to puts(). This optimization // is known as loop unrolling: sergey@snowball armv8 % lldb h2 (lldb) target create "h2" Current executable set to '/Users/user/cs59/armv8/h2' (arm64). (lldb) dis -n main h2`main: h2[0x100003f04] <+0>: stp x20, x19, [sp, #-0x20]! h2[0x100003f08] <+4>: stp x29, x30, [sp, #0x10] h2[0x100003f0c] <+8>: add x29, sp, #0x10 ; =0x10 h2[0x100003f10] <+12>: adr x19, #0xa0 ; "Hello" h2[0x100003f14] <+16>: nop h2[0x100003f18] <+20>: mov x0, x19 h2[0x100003f1c] <+24>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f20] <+28>: mov x0, x19 h2[0x100003f24] <+32>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f28] <+36>: mov x0, x19 h2[0x100003f2c] <+40>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f30] <+44>: mov x0, x19 h2[0x100003f34] <+48>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f38] <+52>: mov x0, x19 h2[0x100003f3c] <+56>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f40] <+60>: mov x0, x19 h2[0x100003f44] <+64>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f48] <+68>: mov x0, x19 h2[0x100003f4c] <+72>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f50] <+76>: mov x0, x19 h2[0x100003f54] <+80>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f58] <+84>: mov x0, x19 h2[0x100003f5c] <+88>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f60] <+92>: mov x0, x19 h2[0x100003f64] <+96>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f68] <+100>: mov x0, x19 h2[0x100003f6c] <+104>: bl 0x100003f80 ; symbol stub for: puts h2[0x100003f70] <+108>: mov w0, #0x2a h2[0x100003f74] <+112>: ldp x29, x30, [sp, #0x10] h2[0x100003f78] <+116>: ldp x20, x19, [sp], #0x20 h2[0x100003f7c] <+120>: ret (lldb) ^D =====> Annotations stop here, to be continued. sergey@snowball armv8 % cd .. sergey@snowball cs59 % cd lisp sergey@snowball lisp % gcl GCL (GNU Common Lisp) 2.6.14 Fri Jan 13 10:47:56 AM EST 2023 ANSI git: Version_2_6_14 Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl) Binary License: GPL due to GPL'ed components: (READLINE UNEXEC) Modifications of this banner must retain notice of a compatible license Dedicated to the memory of W. Schelter Use (help) to get some basic information on how to use GCL. Temporary directory for compiler files: /var/folders/tp/17fq2kwj13bb2xj7s5hbr0ch0000gn/T/ >1 1 >nil NIL >t T >10000000000000000000000000000000000 10000000000000000000000000000000000 >10000000000079287589272987529878579857287539287352983752895729875287598753 10000000000079287589272987529878579857287539287352983752895729875287598753 >(+ 10000000000079287589272987529878579857287539287352983752895729875287598753 1) 10000000000079287589272987529878579857287539287352983752895729875287598754 >(cons + (cons 1 (cons 2 nil))) ((+ 10000000000079287589272987529878579857287539287352983752895729875287598753 1) 1 2) >(cons 1 nil) (1) >(cons 1 (cons nil)) Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by CONS. Condition in CONS [or a callee]: INTERNAL-SIMPLE-PROGRAM-ERROR: CONS [or a callee] requires more than one argument. Broken at CONS. Type :H for Help. 1 Return to top level. >>1 Top level. >(cons 1 (cons 2 nil)) (1 2) >(cons 1 (cons 2 (cons 3 nil))) (1 2 3) >(list 1 2 3) (1 2 3) >(+ 1 2) 3 >(READ READ READ-FROM-STRING READER-METHOD-CLASS READ-BYTE READ-LINE READTABLE READ-CHAR READ-PRESERVING-WHITESPACE READTABLE-CASE READ-CHAR-NO-HANG READ-SEQUENCE READTABLEP READ-DELIMITED-LIST READER-ERROR >(READ-FROM-STRING "(+ 1 2)") (+ 1 2) 7 >(eval (READ-FROM-STRING "(+ 1 2)")) 3 >(print (eval (READ-FROM-STRING "(+ 1 2)"))) 3 3 >+ (PRINT (EVAL (READ-FROM-STRING "(+ 1 2)"))) >#'+ # >x Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by EVAL. Condition in EVAL [or a callee]: INTERNAL-SIMPLE-UNBOUND-VARIABLE: Cell error on X: Unbound variable: Broken at EVAL. Type :H for Help. 1 Return to top level. >>1 Top level. >(+ (* 2 3) 10) 16 >(+ (* 2 3) (- 15 5)) 16 >(quote x) X >x Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by EVAL. Condition in EVAL [or a callee]: INTERNAL-SIMPLE-UNBOUND-VARIABLE: Cell error on X: Unbound variable: Broken at EVAL. Type :H for Help. 1 Return to top level. >>1 Top level. >(set (quote x) 100) 100 >x 100 >(+ x x) 200 >(* x 2) 200 >(consp x) NIL >(atom x) T >(atom 100) T >(atom "foo") T >(atom (cons 1 nil)) NIL >(consp (cons 1 nil)) T >(if (> x 10) "foo" "bar") "foo" >(if (> x 1000) "foo" "bar") "bar" >(if (> x 1000) (set (quote y "foo")) (set (quote y) "bar"))) "bar" >y "bar" >(if (> x 10) (set (quote y "foo")) (set (quote y) "bar"))) Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by QUOTE. Condition in QUOTE [or a callee]: INTERNAL-SIMPLE-PROGRAM-ERROR: Too many arguments. Broken at QUOTE. Type :H for Help. 1 Return to top level. >>1 Top level. >(if (> x 10) (set (quote y) "foo")) (set (quote y) "bar"))) "foo" > "bar" >y "bar" >x 100 >(if (> x 10) (set (quote y) "foo")) (set (quote y) "bar")) "foo" > "bar" >y "bar" >(if (> x 10) (set (quote y) "foo")) (set (quote y) "bar"))) "foo" > "bar" >y "bar" >(if (> x 10) (set (quote y) "foo") (set (quote y) "bar")) "foo" >(if (> x 1000) (set (quote y) "foo") (set (quote y) "bar")) "bar" >y "bar" >(if (> x 10) (set (quote y) "foo") (set (quote y) "bar")) "foo" >y "foo" >(SETQ x 200) 200 >x 200 >(defun plus1 (x) (+ x 1)) PLUS1 >plus1 Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by EVAL. Condition in EVAL [or a callee]: INTERNAL-SIMPLE-UNBOUND-VARIABLE: Cell error on PLUS1: Unbound variable: Broken at EVAL. Type :H for Help. 1 Return to top level. >>1 Top level. >(plus1 15) 16 >#'plus1 (SYSTEM:LAMBDA-BLOCK PLUS1 (X) (+ X 1)) >(FUNC FUNCALL FUNCTION FUNCALLABLE-STANDARD-CLASS FUNCTION-KEYWORDS FUNCALLABLE-STANDARD-INSTANCE FUNCTION-LAMBDA-EXPRESSION FUNCALLABLE-STANDARD-INSTANCE-ACCESS FUNCTIONP >(FUNC FUNCALL FUNCTION FUNCALLABLE-STANDARD-CLASS FUNCTION-KEYWORDS FUNCALLABLE-STANDARD-INSTANCE FUNCTION-LAMBDA-EXPRESSION FUNCALLABLE-STANDARD-INSTANCE-ACCESS FUNCTIONP >(FUNC FUNCALL FUNCTION FUNCALLABLE-STANDARD-CLASS FUNCTION-KEYWORDS FUNCALLABLE-STANDARD-INSTANCE FUNCTION-LAMBDA-EXPRESSION FUNCALLABLE-STANDARD-INSTANCE-ACCESS FUNCTIONP >(FUNCALL plus1 10) Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by EVAL. Condition in EVAL [or a callee]: INTERNAL-SIMPLE-UNBOUND-VARIABLE: Cell error on PLUS1: Unbound variable: Broken at FUNCALL. Type :H for Help. 1 Return to top level. >>1 Top level. >(FUNCALL 'plus1 10) 11 >(FUNCALL (quote plus1) 10) 11 >(FUNCALL 'plus1 10) 11 >'x X >(set 'x 300) 300 >x 300 >(null nil) T >(null '()) T >() NIL >(car '(1 2 3)) 1 >(cdr '(1 2 3)) (2 3) >(cdr (cdr '(1 2 3))) (3) >(car (cdr (cdr '(1 2 3)))) 3 >(car (cdr '(1 2 3))) 2 >(cadr '(1 2 3)) 2 >(cddr '(1 2 3)) (3) >(caddr '(1 2 3)) 3 >(cadddr '(1 2 3 4 5 6 7 7 8 9)) 4 >(caddddr '(1 2 3 4 5 6 7 7 8 9)) Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by EVAL. Condition in EVAL [or a callee]: INTERNAL-SIMPLE-UNDEFINED-FUNCTION: Cell error on CADDDDR: Undefined function: Broken at EVAL. Type :H for Help. 1 Return to top level. >>1 Top level. >(defun caddddr (x) (car (cdr (cdddr x)))) CADDDDR >(caddddr '(1 2 3 4 5 6 7 7 8 9)) 5 >(defun len (x) (if (null x) 0 (+ 1 (len (cdr x))))) LEN >(len '()) 0 >(len '(1)) 1 >(len '(1 2)) 2 >(len '(1 2 3)) 3 >(len '(1 2 3 4)) 4 >(len '(1 2 3 4 5 3 3 4 6 8 3 2)) 12 ====== to be continued ========