From adf9a88bce4d8fce41e5e6c04a186bf26a633a51 Mon Sep 17 00:00:00 2001 From: gapry Date: Thu, 2 Apr 2026 05:45:00 +0800 Subject: [PATCH 1/2] Posts: support HLJS style --- ...f-Compiler-Optimisations-Study-Notes-01.md | 14 +++--- ...f-Compiler-Optimisations-Study-Notes-02.md | 8 ++-- ...f-Compiler-Optimisations-Study-Notes-03.md | 16 +++---- ...f-Compiler-Optimisations-Study-Notes-04.md | 20 ++++----- ...f-Compiler-Optimisations-Study-Notes-05.md | 38 +++++++++------- ...f-Compiler-Optimisations-Study-Notes-06.md | 38 ++++++++-------- ...f-Compiler-Optimisations-Study-Notes-07.md | 2 +- src/components/Header/Header.css | 2 +- .../MarkdownRenderer/MarkdownRenderer.jsx | 44 ++++++++++++++----- src/styles/App.css | 2 +- 10 files changed, 107 insertions(+), 77 deletions(-) diff --git a/public/posts/2026/2026-01-01-Advent-of-Compiler-Optimisations-Study-Notes-01.md b/public/posts/2026/2026-01-01-Advent-of-Compiler-Optimisations-Study-Notes-01.md index 001de13..40a6569 100644 --- a/public/posts/2026/2026-01-01-Advent-of-Compiler-Optimisations-Study-Notes-01.md +++ b/public/posts/2026/2026-01-01-Advent-of-Compiler-Optimisations-Study-Notes-01.md @@ -64,7 +64,7 @@ int main() { $ rm -f (path filter *.o); gcc -O0 -c main.c; llvm-objdump -d --x86-asm-syntax=att main.o ``` -```bash +```x86asm main.o: file format elf64-x86-64 Disassembly of section .text: @@ -90,11 +90,11 @@ text data bss dec hex filename As `-O0`, the compiler generates a stack frame, leading to unnecessary instruction overhead. ###### Use `-O1` as optimization level -``` +```bash $ rm -f (path filter *.o); gcc -O1 -c main.c; llvm-objdump -d --x86-asm-syntax=att main.o ``` -```bash +```x86asm main.o: file format elf64-x86-64 Disassembly of section .text: @@ -121,7 +121,7 @@ It reduces the output from six instructions to three by removing the stack frame $ rm -f (path filter *.o); gcc -O2 -c main.c; llvm-objdump -d --x86-asm-syntax=att main.o ``` -```bash +```x86asm main.o: file format elf64-x86-64 Disassembly of section .text: @@ -154,7 +154,9 @@ $ rm -f (path filter *.o); clang -O1 -c main.c; llvm-objdump -d --x86-asm-syntax ```bash rm -f (path filter *.o); clang -O1 -c main.c; llvm-objdump -d --x86-asm-syntax=att main.o +``` +```x86asm main.o: file format elf64-x86-64 Disassembly of section .text: @@ -183,7 +185,7 @@ long get_val() { $ rm -f (path filter *.o); clang -O2 -c get_val.c; llvm-objdump -d --x86-asm-syntax=att get_val.o ``` -```bash +```x86asm get_val.o: file format elf64-x86-64 Disassembly of section .text: @@ -278,7 +280,7 @@ $ clang -O2 -c main.c $ llvm-objdump -d --disassemble-symbols=f --x86-asm-syntax=att main.o ``` -```bash +```x86asm main.o: file format elf64-x86-64 Disassembly of section .text: diff --git a/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-02.md b/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-02.md index 218de1f..5c2c15f 100644 --- a/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-02.md +++ b/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-02.md @@ -52,7 +52,7 @@ int add(int x, int y) { $ rm -f (path filter *.o); clang -O0 -c add.c; llvm-objdump -d --x86-asm-syntax=att add.o ``` -```bash +```x86asm add.o: file format elf64-x86-64 Disassembly of section .text: @@ -78,7 +78,7 @@ the compiler cannot translate `a = b + c` directly to a single `add` instruction value of `b` or `c` before the operation is executed, the compiler needs to use `mov` instruction to initialize the destination with one of the operands first: -```bash +```x86asm movl -0x4(%rbp), %eax addl -0x8(%rbp), %eax ``` @@ -90,7 +90,7 @@ Hence, the compiler needs to use two instructions to execute the addition at the rm -f (path filter *.o); clang -O2 -c add.c; llvm-objdump -d --x86-asm-syntax=att add.o ``` -```bash +```x86asm add.o: file format elf64-x86-64 Disassembly of section .text: @@ -115,7 +115,7 @@ and the other employing a single `lea` instruction. $ nvim add.s ``` -```text +```x86asm .section .note.GNU-stack, "", @progbits .section .rodata diff --git a/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-03.md b/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-03.md index 213081c..be3ce98 100644 --- a/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-03.md +++ b/public/posts/2026/2026-01-31-Advent-of-Compiler-Optimisations-Study-Notes-03.md @@ -76,7 +76,7 @@ $ qemu-aarch64 ./app.out $ llvm-objdump -d --disassemble-symbols=add app.out ``` -```text +```armasm app.out: file format elf64-littleaarch64 Disassembly of section .text: @@ -108,7 +108,7 @@ Disassembly of section .text: ``` #### Part 01: Function Prologue -```text +```armasm 4007f0: d10083ff sub sp, sp, #0x20 // Allocate 32 bytes on stack 4007f4: a9017bfd stp x29, x30, [sp, #0x10] // Save Frame Pointer (x29) and Link Register (x30) 4007f8: 910043fd add x29, sp, #0x10 // Set up new Frame Pointer @@ -134,7 +134,7 @@ facilitate the Stack Unwinding process during the Function Epilogue. ``` #### Part 02: Parameter Storage -```text +```armasm 4007fc: b81fc3a0 stur w0, [x29, #-0x4] // Store 'x' (w0) into stack 400800: b9000be1 str w1, [sp, #0x8] // Store 'y' (w1) into stack 400804: b9400be8 ldr w8, [sp, #0x8] // Load 'y' from stack into w8 @@ -145,7 +145,7 @@ Since it is at the `-O0` optimization level, an additional instruction is used to load `y` from stack memory back into a register (`w8`) for subsequent conditional evaluation. #### Part 03: Branching -```text +```armasm 400808: 71000108 subs w8, w8, #0x0 // Compare w8 (y) with 0 40080c: 540000a8 b.hi 0x400820 // If y > 0, jump to recursive case (400820) 400810: 14000001 b 0x400814 // Else, branch to base case logic @@ -158,7 +158,7 @@ if `y > 0`, the Program Counter (`PC`) jumps to the Recursive Case; otherwise, it jumps to the Base Case. #### Part 04: The Base Case: `y == 0` -```text +```armasm 400814: b85fc3a0 ldur w0, [x29, #-0x4] // [Base Case] Load 'x' into w0 400818: b90007e0 str w0, [sp, #0x4] // Store 'x' as the potential return value 40081c: 14000008 b 0x40083c // Jump to epilogue (return) (Part 06) @@ -169,7 +169,7 @@ The compiler then executes a `store` operation from register `W0` to stack memor return value. #### Part 05: The Recursive Step: `add(x + 1, y - 1)` -```text +```armasm 400820: b85fc3a8 ldur w8, [x29, #-0x4] // [Recursive Case] Load 'x' into w8 400824: 11000500 add w0, w8, #0x1 // w0 = x + 1 (Preparing 1st argument) 400828: b9400be8 ldr w8, [sp, #0x8] // Load 'y' into w8 @@ -184,7 +184,7 @@ The `bl` (Branch with Link) instruction then executes the recursive call, redire Once the recursive call returns, the resulting value in `w0` is stored into stack memory before jumping to the epilogue. #### Part 06: Function Epilogue -```text +```armasm 40083c: b94007e0 ldr w0, [sp, #0x4] // Load the result from stack into w0 400840: a9417bfd ldp x29, x30, [sp, #0x10] // Restore Frame Pointer and Link Register 400844: 910083ff add sp, sp, #0x20 // Deallocate stack space @@ -212,7 +212,7 @@ $ qemu-aarch64 ./app.out $ llvm-objdump -d --disassemble-symbols=add app.out ``` -```text +```armasm app.out: file format elf64-littleaarch64 Disassembly of section .text: diff --git a/public/posts/2026/2026-02-27-Advent-of-Compiler-Optimisations-Study-Notes-04.md b/public/posts/2026/2026-02-27-Advent-of-Compiler-Optimisations-Study-Notes-04.md index 204b49c..f5934c2 100644 --- a/public/posts/2026/2026-02-27-Advent-of-Compiler-Optimisations-Study-Notes-04.md +++ b/public/posts/2026/2026-02-27-Advent-of-Compiler-Optimisations-Study-Notes-04.md @@ -54,7 +54,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -88,7 +88,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -116,7 +116,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -145,7 +145,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -186,7 +186,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -215,7 +215,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -245,7 +245,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -275,7 +275,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -309,7 +309,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: @@ -340,7 +340,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -c mul.c; llvm-objdump -d --x86-asm-syntax=att mul.o ``` -```text +```x86asm mul.o: file format elf64-x86-64 Disassembly of section .text: diff --git a/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-05.md b/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-05.md index 4c0541b..aaa74c2 100644 --- a/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-05.md +++ b/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-05.md @@ -56,7 +56,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c mul.c; llvm-objdump -d mul.o ``` -```text +```armasm mul.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -88,7 +88,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c mul.c; llvm-objdump -d mul.o ``` -```text +```armasm mul.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -120,7 +120,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c mul.c; llvm-objdump -d mul.o ``` -```text +```armasm mul.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -132,8 +132,10 @@ Disassembly of section .text: ``` ARM Instructions: -- `add , , , lsl #` -- `lsl , , #` +```armasm +add , , , lsl # +lsl , , # +``` The multiplication of 6x is decomposed into two discrete stages. First, the compiler calculates `w8 = w0 + (w0 << 1) = w0 + 2 * w0 = 3 * w0`. @@ -155,7 +157,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c mul.c; llvm-objdump -d mul.o ``` -```text +```armasm mul.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -167,8 +169,10 @@ Disassembly of section .text: ``` ARM Instructions: -- `lsl , , #` -- `sub , , ` +```armasm +lsl , , # +sub , , +``` The compiler implements a shift-and-subtract strategy for constants near powers of two. To compute `7x`, it first executes `w8 = w0 << 3 = 8 * w0` @@ -190,7 +194,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c mul.c; llvm-objdump -d mul.o ``` -```text +```armasm mul.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -202,14 +206,16 @@ Disassembly of section .text: ``` ARM Instructions: -- `mov , ` -- `mul , , ` +```armasm +mov , +mul , , +``` The compiler defaults to the `mul` instruction because decomposing the constant `11` cannot be achieved in only two instructions. If the compiler were to adopt a manual shift-and-subtract strategy, the code generator would need to output three instructions: -```text +```armasm add w8, w0, w0, lsl 1 // w8 = x + 2x = 3x lsl w8, w8, #2 // w8 = w8 << 2 = 3x << 2 = 3x * 4 = 12x sub w0, w8, w0 // w0 = 12x - x = 11x @@ -233,7 +239,7 @@ int mul(int x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c mul.c; llvm-objdump -d mul.o ``` -```text +```armasm mul.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -245,8 +251,10 @@ Disassembly of section .text: ``` ARM Instructions: -- `lsl , , #` -- `sub , , , lsl #` +```armasm +lsl , , # +sub , , , lsl # +``` The computation of 14x demonstrates the flexibility of the sub instruction with shifted operands. The compiler first calculates `w8 = w0 << 4 = 16 * w0`. diff --git a/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-06.md b/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-06.md index bd57b23..0031d25 100644 --- a/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-06.md +++ b/public/posts/2026/2026-02-28-Advent-of-Compiler-Optimisations-Study-Notes-06.md @@ -1,5 +1,5 @@ --- -tags: AoCO2025, Compiler, x86 +tags: AoCO2025, Compiler, x86, arm --- ## Study Notes: Division, Advent of Compiler Optimisations 2025 @@ -44,7 +44,7 @@ int div(int x) { $ rm -f (path filter *.o); clang -O2 -c div.c; llvm-objdump -d --x86-asm-syntax=att div.o ``` -```text +```x86asm div.o: file format elf64-x86-64 Disassembly of section .text: @@ -58,12 +58,12 @@ Disassembly of section .text: ``` Instructions: -```text -- leal (), ; = offset + base -- cmovnsl , ; cmov = conditional move - ; ns = Not Signed - ; cmovns = Conditional Move if Not Sign -- sarl , ; sar = Shift Arithmetic Right +```x86asm +leal (), ; = offset + base +cmovnsl , ; cmov = conditional move + ; ns = Not Signed + ; cmovns = Conditional Move if Not Sign +sarl , ; sar = Shift Arithmetic Right ``` In C, signed integer division truncates toward zero. For example: @@ -141,7 +141,7 @@ unsigned div(unsigned x) { $ rm -f (path filter *.o); clang -O2 -c div.c; llvm-objdump -d --x86-asm-syntax=att div.o ``` -```text +```x86asm div.o: file format elf64-x86-64 Disassembly of section .text: @@ -185,7 +185,7 @@ int div(int x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c div.c; llvm-objdump -d div.o ``` -```text +```armasm div.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -201,13 +201,13 @@ Disassembly of section .text: The reason is the same as in the previous x86 case, we need to know why we need to use `0x1FF`. Instructions: -```text -- add , , #imm ; w8 = w0 + 0x1ff -- cmp , #imm ; Compares w0 with #0x0, and update the processor flags NZCV -- csel , , , ; Conditional Select. - ; If the condition lt (Less Than) is true, it selects w8; - ; otherwise, it selects w0. -- asr , , #imm : Arithmetic Shift Right, w0 = w8 >> 9 +```armasm +add , , #imm ; w8 = w0 + 0x1ff +cmp , #imm ; Compares w0 with #0x0, and update the processor flags NZCV +csel , , , ; Conditional Select. + ; If the condition lt (Less Than) is true, it selects w8; + ; otherwise, it selects w0. +asr , , #imm : Arithmetic Shift Right, w0 = w8 >> 9 ``` | Flag | Name | Bit | Description (when set to 1) | @@ -232,7 +232,7 @@ unsigned div(unsigned x) { $ rm -f (path filter *.o); clang -O2 -target aarch64-linux-gnu -c div.c; llvm-objdump -d div.o ``` -```text +```armasm div.o: file format elf64-littleaarch64 Disassembly of section .text: @@ -243,7 +243,7 @@ Disassembly of section .text: ``` Instruction: -```text +```armasm lsr , , #imm ; Logical Shift Right, that is w0 = w0 >> 9. ``` diff --git a/public/posts/2026/2026-03-31-Advent-of-Compiler-Optimisations-Study-Notes-07.md b/public/posts/2026/2026-03-31-Advent-of-Compiler-Optimisations-Study-Notes-07.md index 5a3a750..ce2ff63 100644 --- a/public/posts/2026/2026-03-31-Advent-of-Compiler-Optimisations-Study-Notes-07.md +++ b/public/posts/2026/2026-03-31-Advent-of-Compiler-Optimisations-Study-Notes-07.md @@ -74,7 +74,7 @@ By disassembling the compiled object file, we can observe the magic number $M$ a clang -O2 -c main.c; llvm-objdump -d --disassemble-symbols=div10 --x86-asm-syntax=att main.o ``` -``` +```x86asm 0000000000000040 : 40: 89 f9 movl %edi, %ecx 42: b8 cd cc cc cc movl $0xcccccccd, %eax # Magic Number M = 0xCCCCCCCD diff --git a/src/components/Header/Header.css b/src/components/Header/Header.css index cb7cf49..234f1bc 100644 --- a/src/components/Header/Header.css +++ b/src/components/Header/Header.css @@ -9,7 +9,7 @@ display: flex; justify-content: space-between; align-items: center; - max-width: 800px; + max-width: 1024px; margin: 0 auto; padding: 0 0px; box-sizing: border-box; diff --git a/src/components/MarkdownRenderer/MarkdownRenderer.jsx b/src/components/MarkdownRenderer/MarkdownRenderer.jsx index 958faff..c678911 100644 --- a/src/components/MarkdownRenderer/MarkdownRenderer.jsx +++ b/src/components/MarkdownRenderer/MarkdownRenderer.jsx @@ -3,27 +3,47 @@ import remarkGfm from 'remark-gfm'; import remarkMath from 'remark-math'; import rehypeKatex from 'rehype-katex'; import 'katex/dist/katex.min.css'; -import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; -import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism'; +import { Prism as PrismHighlighter } from 'react-syntax-highlighter'; +import { Light as HLJSHighlighter } from 'react-syntax-highlighter'; +import { atomDark as PrismStyles } from 'react-syntax-highlighter/dist/esm/styles/prism'; +import { darcula as HLJSStyles } from 'react-syntax-highlighter/dist/esm/styles/hljs'; import './MarkdownRenderer.css' +const HLJS_LANGS = ['x86asm', 'armasm']; + +const HLJSCodeBlock = ({ language, content, ...props }) => ( + + {content} + +); + +const PrismCodeBlock = ({ language, content, ...props }) => ( + + {content} + +); + const CodeBlock = ({ inline, className, children, ...props }) => { const match = /language-(\w+)/.exec(className || ''); if (!inline && match) { const language = match[1]; const content = String(children).replace(/\n$/, ''); + + const isHLJS = HLJS_LANGS.includes(language); + const Component = isHLJS ? HLJSCodeBlock : PrismCodeBlock; - return ( - - {content} - - ); + return ; } return ( diff --git a/src/styles/App.css b/src/styles/App.css index 62a87a2..c921c9e 100644 --- a/src/styles/App.css +++ b/src/styles/App.css @@ -7,7 +7,7 @@ body { } .app-shell { - max-width: 800px; + max-width: 1024px; margin: 0 auto; padding: 0px 20px; line-height: 1.7; From e344b494566232873a9e426879eabdcc079a0ac9 Mon Sep 17 00:00:00 2001 From: gapry Date: Thu, 2 Apr 2026 05:55:31 +0800 Subject: [PATCH 2/2] Posts: support HLJS style: fix --- src/components/MarkdownRenderer/MarkdownRenderer.jsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/MarkdownRenderer/MarkdownRenderer.jsx b/src/components/MarkdownRenderer/MarkdownRenderer.jsx index c678911..7752035 100644 --- a/src/components/MarkdownRenderer/MarkdownRenderer.jsx +++ b/src/components/MarkdownRenderer/MarkdownRenderer.jsx @@ -9,6 +9,12 @@ import { atomDark as PrismStyles } from 'react-syntax-highlighter/dist/esm/style import { darcula as HLJSStyles } from 'react-syntax-highlighter/dist/esm/styles/hljs'; import './MarkdownRenderer.css' +import x86asm from 'react-syntax-highlighter/dist/esm/languages/hljs/x86asm'; +import armasm from 'react-syntax-highlighter/dist/esm/languages/hljs/armasm'; + +HLJSHighlighter.registerLanguage('x86asm', x86asm); +HLJSHighlighter.registerLanguage('armasm', armasm); + const HLJS_LANGS = ['x86asm', 'armasm']; const HLJSCodeBlock = ({ language, content, ...props }) => (