Skip to content

Instantly share code, notes, and snippets.

@iximeow
Created December 29, 2019 11:20
Show Gist options
  • Save iximeow/ed6bdd0c0dc81bfaf5e4037ac67356a8 to your computer and use it in GitHub Desktop.
Save iximeow/ed6bdd0c0dc81bfaf5e4037ac67356a8 to your computer and use it in GitHub Desktop.
what does Sz bit do in protected mode
; build and run: `nasm segment_heccery.asm -f bin -o img.bin && qemu-system-x86_64 img.bin -s -S`
[BITS 16]
[ORG 7c00h]
init:
cli
lgdt [gdtr]
mov eax, cr0
or al, 1
mov cr0, eax
jmp 0x08:protected_mode
protected_mode:
[BITS 32]
mov ax, 0x10
mov ds, ax
mov ss, ax
add eax, 8
mov es, ax
; now, we are in 32-bit protected mode.
; the theory is that using ds makes for 32-bit memory access,
; where using es will make for 16-bit memory access. test this with lea.
; 8d 03 with 32-bit addressing will be `lea eax, [ebx]`.
; 8d 03 in 16-bit addressing will be `lea eax, [bx + si]`.
; for completeness, also test 16-bit addressing with address-size override (should be 32-bit)
; tested under qemu, because it's easy.
xor eax, eax
xor edi, edi
dec edi
mov ebx, 0xaabbccdd
mov esi, 0x12341234
db 0x8d, 0x03
; eax should be 0xaabbccdd now.
; [x] it is
xor eax, eax
db 0x67, 0x8d, 0x03
; eax should be 0xdf11??
; [ ] it is not! (it is 0xffff)
xor edx, edx
db 0x26, 0x8d, 0x13
; edx should be 0xccdd + 0x1234 == 0xdf11
; [ ] it is not! (it is 0xaabbccdd)
xor edx, edx
db 0x67, 0x26, 0x8d, 0x13
; edx should be 0xbcefdf11
; [ ] it is not! (it is 0xffff)
; so, using at 16-bit data segment appears to have no effect. a closer reading of the intel sdm agrees:
; From 3.4.5, "Segment Descriptors" (vol.3A, 3-9):
; D/B (default operation size/default stack pointer size and/or upper bound) flag
; Performs different functions depending on whether the segment descriptor is an executable code
; segment, an expand-down data segment, or a stack segment. (This flag should always be set to 1
; for 32-bit code and data segments and to 0 for 16-bit code and data segments.)
;
; now, es selects a descriptor that matches none of these.
; * not executable
; * not expand-down
; * not a stack segment
;
; so the only applicable part appears to be "should be 0 for 16-bit data segments."
;
; later, talking about executable segments directly:
; Executable code segment. The flag is called the D flag and it indicates the default length for
; effective addresses and operands referenced by instructions in the segment. If the flag is set,
; 32-bit addresses and 32-bit or 8-bit operands are assumed; if it is clear, 16-bit addresses and
; 16-bit or 8-bit operands are assumed.
; The instruction prefix 66H can be used to select an operand size other than the default, and the
; prefix 67H can be used select an address size other than the default.
;
; which is what i had thought this bit of data segments was selecting.
hang:
jmp hang
gdt_records:
; null record
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
; set a descriptor up for code
db 0xff, 0xff ; limit
db 0x00, 0x00 ; base (0:15)
db 0x00 ; base (16:23)
db 0x9a ; access byte: set present, executable, and rw
db 0xcf ; set Gr, Sz, and limit 16:19
db 0x00 ; base (24:31)
; set a descriptor up for data
db 0xff, 0xff ; limit
db 0x00, 0x00 ; base (0:15)
db 0x00 ; base (16:23)
db 0x92 ; access byte: set present, data, and rw
db 0xcf ; set Gr, Sz, and limit 16:19
db 0x00 ; base (24:31)
; set a descriptor up for 16-bit data
db 0xff, 0xff ; limit
db 0x00, 0x00 ; base (0:15)
db 0x00 ; base (16:23)
db 0x92 ; access byte: set present, data, and rw
db 0x8f ; set Gr, Sz, and limit 16:19 -- 16-bit!!!
db 0x00 ; base (24:31)
gdtr:
dw 0x20
dd gdt_records
times 510-($-$$) db 0
db 0x55
db 0xaa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment