In another post of mine, there was some discussion about a small area just above (see end of page @) BDA (500H - 534H) that handles DOS
print screen. As not to interfere with this, as it would only gain me three entries anyway, map data will begin @ 540H. The addresses for this snippet are offsets from 838H, therefore,
838H + 2BH - 540H = 323H (803) bytes can be overwritten. The code could be shortened by hard coding maximum 40 entries, but I want this to stay relative.
Code is fashioned somewhat after this example albeit it is really bloated, with functionality that I don't think is really necessary.
Begin by initializing segment registers and
ES:DI is the pointer to buffer for INT 15H.
0 B85400 mov ax, 0x54 ; Just above BDA 3 8EC0 mov es, ax 5 8ED8 mov ds, ax 7 31FF xor di, di
Everything from 540H to offset 2BH (863H) can be overwritten. Doubt seriously any system will have 40 entries, but one never knows.
9 8CC9 mov cx, cs ; Base segment of this code B C1E104 shl cx, 4 ; Convert to absolute addr E 81C16302 add cx, 0x263 ; Offset from CS*16 to 2DH 12 C1E004 shl ax, 4 ; Convert code segment 15 29C1 sub cx, ax ; Total bytes
At the first iteration, the length of each entry is returned in CL, which is 20, then it will be calculated how many entries will fit in this space, meanwhile this value needs to be preserved.
17 894E01 mov [bp+1], cx
Finally, EBX, ECX, EDX & AX need to be setup for INT 15H
1A 6631C9 xor ecx, ecx 1D 6689CB mov ebx, ecx 20 B120 mov cl, 0x20 22 66BA50414D53 mov edx, 0x534d4150 ; = 'SMAP' NOTE: Interrupt doesn't care about high order bits (31-16) of EAX. This might be the case with ECX & EBX too, but I haven't experimented with that. 28 B820E8 mov ax, 0xe820
Infinite loop until one of six conditions occurs
2B 50 push ax 2C 6652 push edx 2E CD15 int 15H 30 7233 jc 65 ; Continue until CF = 1
Continuation counter in BL is the next most significant value to be evaluated.
32 80FB01 cmp bl, 1 35 722E jc 65 ; BL = 0, last entry has been read 37 770F ja 0x48 ; BL > 1 continue reading entries
For some reason, only on first iteration does the signature in EDX need to be compared
39 6639D0 cmp eax, edx 3C 7527 jnz 65 ; EAX <> 'SMAP' Calculation of max entries can be made now which will equal 40 in this version 3E 8B4601 mov ax, [bp+1] 41 31D2 xor dx, dx 43 F7F1 div cx ; Probably 14H (20) 45 894601 mov [bp+1], ax
Unless I'm missing something, the linked example set first byte of next entry to 1. If that byte is overwritten, it has something to do with ACPI 3.0, but CL being greater than 20 does the same. Is my thinking flawed?
48 E316 jcxz 60 4A 80F914 cmp cl, 20 4D 7711 ja 60
Haven't quite figured out why BIOS would return a zero length entry, but those entries are simply ignored by doing this
4F 668B4508 mov eax,[di+8] ; Read high order bits 53 660B450C or eax,[di+12] ; ZF = 1, null length entry 57 7407 jz 60
Have we run out of space yet, which is very unlikely
59 FE4E01 dec [bp+1] 5C 7407 jz 65
Point to next position and restore AX & EDX for next round
5E 01CF add di,cx 60 665A pop edx 62 58 pop ax 63 EBC6 jmp 2B This is where error conditions will be evaluated, but at this point not really sure what that has to be yet. 65 90 nop