alloc(mapBase, 0x190)        // MAP[20][20] = 400 bytes
alloc(visitedBase, 0x190)    // Visited[20][20]
alloc(prevBase, 0xC80)       // Prev[20][20][2 400 ô × 8 bytes = 3200 bytes
alloc(queueBase, 0xC80)      // Queue[400][2] = 3200 bytes
alloc(pathBase, 0xC80)       // Path[400][2] = 3200 bytes
alloc(BFS, 4096)           // front, rear, sx, sy, gx, gy
alloc(newmem, 8048) // value front, rear, sx, sy, gx, gy

alloc(mapBase, 0x9C4)        // 2500 bytes
alloc(visitedBase, 0x9C4)    // 2500 bytes
alloc(prevBase, 0x1388)      // 20,000 bytes
alloc(queueBase, 0x1388)     // 20,000 bytes
alloc(pathBase, 0x1388)      // 20,000 bytes
alloc(BFS, 0x1000)             // giữ nguyên 4096
alloc(newmem, 0x2000)          // giữ nguyên 8192



label(startBFS)
registersymbol(startBFS)

//local addr = getAddress("startBFS")
//executeCode(addr)



BFS:
// Gọi khởi tạo BFS
startBFS:


//mov byte ptr [mapBase+111], 'x'   // x = 13, y = 13
//mov byte ptr [mapBase+112], 'x'   // x = 14, y = 13
//mov byte ptr [mapBase+113], 'x'   // x = 15, y = 13

//mov byte ptr [mapBase+71], 'x'   // x = 13, y = 13
//mov byte ptr [mapBase+72], 'x'   // x = 14, y = 13
//mov byte ptr [mapBase+73], 'x'   // x = 15, y = 13

//mov byte ptr [mapBase+41], 'x'   // x = 13, y = 13
//mov byte ptr [mapBase+42], 'x'   // x = 14, y = 13
//mov byte ptr [mapBase+43], 'x'   // x = 15, y = 13


// Ghi giá trị:

mov r14, newmem                // r14 = base của newmem

mov [r14+0], 0   // $front = 0  r10 = $front
mov [r14+4], 1   // $rear = 1   r11 = $rear

mov [r14+10], (Int)9   // $sx  rsi = $sx
mov [r14+14], (Int)11   // $sy  rdi = $sy
mov [r14+20], (Int)19   // $gx  r12 = $gx
mov [r14+24], (Int)19   // $gy  r13 = $gy

mov [r14+30], (Int)10 // $px
mov [r14+34], (Int)10 // $py

mov r10d, [r14+0] // Global $front = 0
mov r11d, [r14+4] // Global $rear = 1

mov rsi, [r14+10] // Global rsi = $sx
mov rdi, [r14+14] // Global rdi = $sy


mov r15, queueBase             // r15 = base của Queue

mov [r15+0],rsi // $Queue[0][0] = $sx
mov [r15+4],rdi //  $Queue[0][1] = $sy

// Gán "s" vào MAP[$sx][$sy]

mov r14, newmem
mov esi, [r14+10]        // $sx = 9
mov edi, [r14+14]        // $sy = 11

imul edx, esi, (Int)20        // edx = $sx * 20
add edx, edi             // edx = $sx * 20 + $sy

mov rsi, mapBase         // base của MAP
mov r14, rsi
add r14, edx             // rax = địa chỉ MAP[$sx][$sy]
mov byte ptr [r14], 's'  // gán ký tự 's'


//Gán "g" vào MAP[$gx][$gy]
mov r14, newmem
mov esi, [r14+20]        // $gx
mov edi, [r14+24]        // $gy

imul edx, esi, (Int)20
add edx, edi             // edx = $gx * 20 + $gy

mov rsi, mapBase
mov r14, rsi
add r14, edx
mov byte ptr [r14], 'g'  // gán ký tự 'g'

//  $Visited[$sx][$sy] = 1
mov r14, newmem   // base của newmem

mov esi, [r14+10] // Global esi = $sx = 10
mov edi, [r14+14] // Global edi = $sy = 10

mov r14, visitedBase   // base của Visited

mov rdx, esi           // rdx = $sx
imul rdx, (Int)20           // rdx = $sx * 20
add rdx, edi           // rdx = $sx * 20 + $sy

mov byte ptr [r14+rdx], 1   // Visited[$sx][$sy] = 1


// Func BFS_Search($gx, $gy) ----------------------------------------

mov r14, newmem                // r14 = base của newmem
mov r15, queueBase             // r15 = base của Queue

mov r10d, [r14+0]              // r10d = front
mov r11d, [r14+4]              // r11d = rear
mov r12d, [r14+20]             // r12d = gx
mov r13d, [r14+24]             // r13d = gy

mov ecx, 1                     // ecx = i = 1

LoopStart:
cmp ecx, 9C4                 // For $i = 1 to 2500
jge LoopEnd


cmp r10d, r11d                 // If $front < $rear Then
jge SkipBody

imul r8d, r10d, 8              // offset = front * 8
mov rdx, r15                   // rdx = base của Queue
add rdx, r8                    // rdx = Queue + offset

mov esi, [rdx]                 // $x = Queue[front][0]
mov edi, [rdx+4]               // $y = Queue[front][1]




inc r10d                       // $front += 1

cmp esi, r12d                  // If $x = $gx
jne SkipCheck
    cmp edi, r13d                  // And $y = $gy
    jne SkipCheck

// Đến đích rồi → dùng lại thanh ghi thoải mái

jmp LoopEnd                    // ExitLoop nếu đến đích

SkipCheck:


mov [r14+30], esi // lưu $x cũ
mov [r14+34], edi // lưu $y cũ


mov r9d, 0                     // For $d = 0 to 3
DirectionLoop:
cmp r9d, 4                     // kiểm tra d < 4
jge EndDirection

//mov eax, esi                   // $nx = $x bị lỗi ghi hỏng esi
//mov ebx, edi                   // $ny = $y bị lỗi ghi hỏng edi
mov eax, [r14+30]                   // load $nx = $x cũ
mov ebx, [r14+34]                   // load $ny = $y cũ


cmp r9d, 0
jne Case1
dec ebx                        // Case 0: $ny -= 1 → đi sang trái (←)
jmp AfterSwitch

Case1:
cmp r9d, 1
jne Case2
inc ebx                        // Case 1: $ny += 1 → đi sang phải (→) lỗi
jmp AfterSwitch

Case2:
cmp r9d, 2
jne Case3
dec eax                        // Case 2: $nx -= 1 → đi lên (↑)
jmp AfterSwitch

Case3:
inc eax                        // Case 3: $nx += 1 → đi xuống (↓) lỗi

AfterSwitch:
mov rsi, eax                   // rsi = nx hiện tại
mov rdi, ebx                   // rdi = ny hiện tại


// If $nx < 0 Or $ny < 0 Or $nx >= 20 Or $ny >= 20 Then ContinueLoop
cmp rsi, 0                     // $nx < 0
jl SkipDirection
cmp rdi, 0                     // $ny < 0
jl SkipDirection
cmp rsi, (Int)20                    // $nx >= 20
jge SkipDirection
cmp rdi, (Int)20                    // $ny >= 20
jge SkipDirection
// end kiểm tra biên




// If $MAP[$nx][$ny] = "x" Or $Visited[$nx][$ny] = 1 Then ContinueLoop
mov r8d, rsi
imul r8d, (Int)20
add r8d, rdi                   // r8d = nx * 20 + ny

mov rdx, mapBase
add rdx, r8
mov al, [rdx]                  // đọc MAP[nx][ny]
cmp al, 'x'                    // nếu là 'x' thì bỏ qua
je SkipDirection


mov rdx, visitedBase
add rdx, r8
mov al, [rdx]                  // kiểm tra Visited[nx][ny] = 1

cmp al, 1
je SkipDirection


// end kiểm tra chướng ngại và đã đi

mov [r14+40], rsi // lưu $nx hiện tại
mov [r14+44], rdi // lưu $ny hiện tại


// $Visited[$nx][$ny] = 1
mov rdx, visitedBase

mov r8d, rsi
imul r8d, (Int)20
add r8d, rdi                   // r8d = nx * 20 + ny

add rdx, r8
mov byte ptr [rdx], 1


// $Prev[$nx][$ny][0] = $x
// $Prev[$nx][$ny][1] = $y
mov eax, rsi       // rsi = nx
imul eax, (Int)20
add eax, rdi       // eax = nx * 20 + ny
imul eax, 8
mov rdx, prevBase
add rdx, eax

mov rsi, [r14+30]                   // load $x lúc đầu
mov rdi, [r14+34]                   // load $y lúc đầu

mov [rdx], rsi       // x hiện tại
mov [rdx+4], rdi     // y hiện tại


mov rsi, [r14+40]                   // load $nx hiện tại
mov rdi, [r14+44]                   // load $ny hiện tại

// $Queue[$rear][0] = $nx
// $Queue[$rear][1] = $ny
mov eax, r11d        // eax = rear
imul eax, 8          // eax = rear * 8
mov rdx, queueBase
add rdx, eax
mov [rdx+0], rsi       // Queue[rear][0] = nx
mov [rdx+4], rdi     // Queue[rear][1] = ny

//mov r10d, r11d        // eax = rear bớt đường đi
inc r11d             // $rear += 1


SkipDirection:
inc r9d                       // d++
jmp DirectionLoop

EndDirection:
SkipBody:
inc ecx                       // i++
jmp LoopStart

LoopEnd:



push r15
mov r15, newmem+1000        // r15 = địa chỉ bắt đầu ghi đường đi 4096 = 0x1000
mov r14, newmem             // r14 = base chứa các biến sx, sy, gx, gy

mov esi, [r14+20]           // esi = gx (tọa độ x đích)
mov edi, [r14+24]           // edi = gy (tọa độ y đích)

xor rbx, rbx                // rbx = số bước đã ghi = 0

LoopBack:
    cmp rbx, (Int)400       // giới hạn số bước tối đa
    jge ExitLoop            // nếu vượt quá → thoát

    imul rcx, rbx, 8        // rcx = offset của bước thứ rbx
    add rcx, 4              // bỏ qua ô đầu tiên chứa số bước
    mov rdx, r15
    add rdx, rcx            // rdx = địa chỉ ghi bước hiện tại

    mov [rdx], esi          // ghi x vào Path[rbx][0]
    mov [rdx+4], edi        // ghi y vào Path[rbx][1]
    inc rbx                 // tăng số bước

    // === Truy ngược từ prevBase[x][y] ===
    mov eax, esi            // eax = x
    imul eax, (Int)20            // x * 20
    add eax, edi            // x * 20 + y
    imul eax, 8             // offset trong prevBase
    mov r13, prevBase
    add r13, eax            // r13 = địa chỉ prevBase[x][y]

    mov esi, [r13]          // esi = px (tọa độ x bước trước)
    mov edi, [r13+4]        // edi = py (tọa độ y bước trước)

    // === Kiểm tra đã về tới nguồn chưa ===
    cmp esi, [r14+10]       // sx
    jne LoopBack
    cmp edi, [r14+14]       // sy
    jne LoopBack

    // === Ghi bước cuối cùng (nguồn) ===
    cmp rbx, (Int)400
    jge ExitLoop

    imul rcx, rbx, 8
    add rcx, 4
    mov rdx, r15
    add rdx, rcx

    mov [rdx], esi          // ghi sx vào Path[rbx][0]
    mov [rdx+4], edi        // ghi sy vào Path[rbx][1]
    inc rbx

ExitLoop:
mov [r15], rbx              // ghi tổng số bước vào Path[0]
pop r15                     // khôi phục r15






ret                           // kết thúc an toàn


//  $Visited[$sx][$sy] = 1
mov r14, newmem   // base của newmem

mov esi, [r14+10] // Global esi = $sx = 10
mov edi, [r14+14] // Global edi = $sy = 10

mov r14, visitedBase   // base của Visited

mov rdx, esi           // rdx = $sx
imul rdx, (Int)20           // rdx = $sx * 20
add rdx, edi           // rdx = $sx * 20 + $sy

mov byte ptr [r14+rdx], 3   // Visited[$sx][$sy] = 1


//  $Visited[$sx][$sy] = 1
mov r14, newmem   // base của newmem

mov esi, [r14+20] // Global esi = $gx = 10
mov edi, [r14+24] // Global edi = $gy = 10

mov r14, visitedBase   // base của Visited

mov rdx, esi           // rdx = $sx
imul rdx, (Int)20           // rdx = $sx * 20
add rdx, edi           // rdx = $sx * 20 + $sy

mov byte ptr [r14+rdx], 5   // Visited[$sx][$sy] = 1








jmp mapBase
jmp visitedBase
jmp prevBase
jmp queueBase
jmp pathBase
jmp BFS
jmp newmem










