GDB disassembly uses inconsistent register naming - debugging

I'm debugging/disassembling a very simply C program I wrote just for learning purposes. However, I notice that GDB appears to be using inconsistent notation for the registers between the disassembled output and what it tells me when I enter "info registers" after a breakpoint.
Here is part of the disassembled output (around my breakpoint):
0x0000000100000d15 <main+181>: xor %dl,%dl
0x0000000100000d17 <main+183>: mov %ecx,%edi
0x0000000100000d19 <main+185>: mov %dl,%al
0x0000000100000d1b <main+187>: callq 0x100000da0 <checkLicense>
0x0000000100000d20 <main+192>: mov %eax,%ecx
0x0000000100000d22 <main+194>: cmp $0x0,%ecx
0x0000000100000d25 <main+197>: je 0x100000d47 <main+231>
0x0000000100000d27 <main+199>: lea 0x1bb(%rip),%rax # 0x100000ee9
0x0000000100000d2e <main+206>: mov %rax,%rdi
And here is part of the output I get when I call the "info registers" command in GDB:
(gdb) info registers
rax 0x1 1
rbx 0x0 0
rcx 0x1 1
rdx 0x1 1
rsi 0x3 3
rdi 0x3 3
I set my breakpoint where the cmp operation occurs. As you can see it is comparing the value in register ECX to 0, however, it doesn't appear that ECX is a real register. When I get the result of "info registers" it does appear to return real registers, namely rcx. When I try to manipulate the registers in GDB using "set $ecx = 1" for example, it has no effect, however when I do "set $rcx = 1", it does seem to work.
What's up with this inconsistency and is there a way to fix it?

What's up with this inconsistency?
The instruction cmp $0x0,%ecx compares lower 32-bits of register rcx with 0, so the disassembly is correct.
"info registers" it does appear to return real registers, namely rcx
Correct.
"set $ecx = 1" for example, it has no effect
It does have effect for me:
(gdb) info reg rcx
rcx 0xffffffffffffffff -1
(gdb) set $ecx = 0
(gdb) info reg rcx
rcx 0xffffffff00000000 -4294967296
If set $ecx = 1 really has no effect for you, it might be a GDB bug.

Related

How can I check if my syscall failed in NASM

I would like to know if anybody has a solution to my problem.
I'm doing a project for school. This project is about creating a function (only in NASM) that uses a syscall (I have to create ft_read which reproduces the behaviour of the real read system call).
Here is the situation :
When everything is okay (FD, buff, count), my function works properly.
BUT I don't know how to check if the syscall was successful or if it failed.
For example : When I use a fake fd (-1 for example), the syscall read returns 9 in rax.
I understood that 9 is the error code for the variable Errno.
The problem is that I don't know how to differentiate the error code for errno from the return value of read (red of 9 char from the file).
If anybody has an idea on how to do I would be glad to know !
Here is my code at the moment :
extern ___error
SYS_READ_MAC equ 0x2000003
SYS_READ_LINUX equ 3
section .text
global _ft_read
_ft_read:
cmp rdi, 0
jl _error
cmp rsi, 0
je _error
cmp rdx, 0
jl _error
mov rax, SYS_READ_MAC
syscall
cmp rax, 0
jl _error
ret
_error:
mov r10, rax
call ___error
mov qword [rax], r10
mov rax, -1
ret
Sorry if my english isn't perfect, i'm not a native english speaker.
I found my answer :
I didn't realized it, and I don't know exactly why, but I was set on unsigned mode.
So I can't see if rax contains a negative value.
In unsigned mode, the carry flag (CF) is set at 1 if the last operation (or the last syscall ?) failed.
So the solution was to do : JC _error (jump to error if carry flag is set on 1).
My code now :
extern ___error
SYS_READ_MAC equ 0x2000003
SYS_READ_LINUX equ 3
section .text
global _ft_read
_ft_read:
mov rax, SYS_READ_MAC
syscall
jc _error
ret
_error:
mov r10, rax
call ___error
mov qword [rax], r10
mov rax, -1
ret

Calling FormatMessageA from a 64 bit assembler program

I've been working for days on an assembler subroutine to call Windows API function FormatMessageA, and I think I must have some systematic misunderstanding. My routine is shown below. I have traced it in debug mode, and I know that at the time the function is called: rcx has hex 1B00, which is the flag values I specified (dwFlags); rdx has hex 33, which is the bogus initial handle value that I plugged in to provoke the error (lpSource); r8 has 6, which is the error message number that was returned by GetLastError, which equates to ERROR_INVALID_HANDLE (dwMessageId); r9 has 0, for default language (dwLanguageId); rsp+32 has the address of msgptrp, which is my area to receive the address of the error message as allocated by the called function (lpBuffer); rsp+40 has hex 28, or decimal 40, which is the minimum number of characters I arbitrarily specified for the error message (nSize); and rsp+48 has the address of argmntsp, which according to the documentation should be ignored with the flags I specified (*Arguments).
If there's a problem, and obviously there is since rax is returned as zero, I suspect that it has to do with lpBuffer, which the documentation says has data type LPTSTR, whatever that is. Sometimes I want to shout, "Okay, that's what it is in terms of C++, but what is it really? I hope someone can easily spot where I ran off the rails, because I'm at my wits' end with this, and it's something I need to get working in order to do effective error checking for my future endeavors.
goterr PROC
;
.data
; flag values used:
; hex 00000100 FORMAT_MESSAGE_ALLOCATE_BUFFER
; hex 00000200 FORMAT_MESSAGE_IGNORE_INSERTS
; hex 00000800 FORMAT_MESSAGE_FROM_HMODULE
; hex 00001000 FORMAT_MESSAGE_FROM_SYSTEM
flagsp dd 00001B00h ; those flags combined
saveinitp dq ?
bmaskp dq 0fffffffffffffff0h
savshadp dq ?
msgptrp dq ?
handlep dd ?
argmntsp dd ?
;
.code
mov saveinitp, rsp ; save initial contents of stack pointer in this proc
sub rsp, 56 ; shadow space (max of 7 parameters * 8)
and rsp, bmaskp ; make sure it's 16 byte aligned
mov savshadp, rsp ; save address of aligned shadow area for this proc
;
mov handlep, ecx ; save passed I/O handle value locally
;
call GetLastError ; get the specific error
;
mov rsp, savshadp ; shadow area for this proc
mov ecx, flagsp ; flags for Windows error routine
mov edx, handlep ; handle passed from caller
mov r8d, eax ; msg id from GetLastError in low order dword
mov r9, 0 ; default language id
lea rax, msgptrp ; pointer to receive address of msg buffer
mov [rsp+32], rax ; put it on the stack
mov rax, 40 ; set lower doubleword to minimum size for msg buffer
mov [rsp+40], rax ; put it on the stack
lea rax, argmntsp ; variable arguments parameter (not used)
mov [rsp+48], rax ; put it on the stack
call FormatMessageA ; if rax eq 0 the called failed, otherwise rax is no chars.
mov rsp, saveinitp ; restore initial SP for this proc
ret
goterr ENDP

How to use the monitor / mwait instructions in x86-64 assembly on Mac or baremetal

Originally I asked about umonitor and umwait, but it turns out as #harold suggested, that you can't even buy a processor that has those instructions yet. So this question is about monitor and mwait, because I am interested how to use those on baremetal.
I just learned of monitor/mwait.
I would have thought that there would be no evaluation of any instructions once mwait is called, so I don't understand how other parts of memory could be written to. Unless perhaps this is some multithreaded stuff with shared memory of some sort, which I don't fully think I understand.
Wondering if one could whip up a quick hello world program to demonstrate how to use these instructions. My attempt at it is this.
global _main
section .text
_main:
call print1
; watch when address 1000
; (randomly chosen)
; is written to.
mov eax, 1000
monitor eax
; wait for 100 ms, not sure
; or some interrupt
mov eax, 100
mwait eax
call print2
call exit
print2:
mov rdx, msg2.len
mov rsi, msg2
mov rdi, 1
mov rax, 0x2000004
syscall
ret
print1:
mov rdx, msg1.len
mov rsi, msg1
mov rdi, 1
mov rax, 0x2000004
syscall
ret
exit:
mov rdi, 0 ; exit status
mov rax, 0x2000001 ;: exit
syscall
section .data
msg1: db "start", 0xa, 0
.len: equ $ - msg1
msg2: db "end", 0xa, 0
.len: equ $ - msg2
What I'm wondering is what an example usage looks like for (a) a timespan like 100ms delay, and/or (b) an "event" of writing to a specific part of memory to trigger the callback, and/or (c) an external event like keyboard interrupt or ctrl+c interrupt if there is such a thing. Or perhaps the timing thing is done with tpause.
Trying the following with tpause I get error: invalid combination of opcode and operands:
mov eax, 1000
mov edx, 1000
mov rdi, 0
tpause rdi, edx, eax
The few resources I've found:
https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf
https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-303.html
https://software.intel.com/en-us/articles/how-to-use-the-monitor-and-mwait-streaming-simd-extensions-3-instructions
http://blog.andy.glew.ca/2010/11/httpsemipublic.html

NASM 64-bit OS X Inputted String Overwriting Bytes of Existing Value

I am trying to write a simple assembly program to add two numbers together. I want the user to be able to enter the values. The problem I am encountering is that when I display a string message and then read a value in, the next time the string is required the first x characters of the string have been overwritten by the data that was entered by the user.
My assumption is that this is related to the use of LEA to load the string into the register. I have been doing this because Macho64 complains if a regular MOV instruction is used in this situation (something to do with addressing space in 64-bits on the Mac).
My code is as follows:
section .data ;this is where constants go
input_message db 'Please enter your next number: '
length equ $-input_message
section .text ;declaring our .text segment
global _main ;telling where program execution should start
_main: ;this is where code starts getting executed
mov r8, 0
_loop_values:
call _get_value
call _write
inc r8 ;increment the loop counter
cmp r8, 2 ;compare loop counter to zero
jne _loop_values
call _exit
_get_value:
lea rcx, [rel input_message] ;move the input message into rcx for function call
mov rdx, length ;load the length of the message for function call
call _write
call _read
ret
_read:
mov rdx, 255 ;set buffer size for input
mov rdi, 0 ;stdout
mov rax, SYSCALL_READ
syscall
mov rdx, rax ;move the length from rax to rdx
dec rdx ;remove new line character from input length
mov rcx, rsi ;move the value input from rsi to rcx
ret
_write:
mov rsi, rcx ;load the output message
;mov rdx, rax
mov rax, SYSCALL_WRITE
syscall
ret
_exit:
mov rax, SYSCALL_EXIT
mov rdi, 0
syscall
The program loops twice as it should. The first time I get the following prompt:
Please enter your next number:
I would the enter something like 5 (followed by the return key)
The next prompt would be:
5
ease enter your next number:
Any assistance would be much appreciated.
I think all 64-bit code on Mac is required to be rip relative.
Absolute addresses are not supported. in this type of addressing you address your symbol relative to rip.
NASM documentation says:
default abs
mov eax,[foo] ; 32−bit absolute disp, sign−extended
mov eax,[a32 foo] ; 32−bit absolute disp, zero−extended
mov eax,[qword foo] ; 64−bit absolute disp
default rel
mov eax,[foo] ; 32−bit relative disp
mov eax,[a32 foo] ; d:o, address truncated to 32 bits(!)
mov eax,[qword foo] ; error
mov eax,[abs qword foo] ; 64−bit absolute disp
and you can also see this question.

Bootloader memory location

This is a part of a bootloader that I am studying from
`[ORG 0x00]
[BITS 16]
SECTION .text
jmp 0x07c0:START ; set CS(segment register) to 0x07C0 and jump to START label.
TOTALSECTORCOUNT:
dw 0x02
KERNEL32SECTORCOUNT:
dw 0x02
START:
mov ax, 0x07c0
mov ds, ax ; set DS(segment register) to the address of the bootloader.
mov ax, 0xb800
mov es, ax ; set ES(segment register) to the address of the video memory starting address.
; stack initialization
mov ax, 0x0000
mov ss, ax
mov sp, 0xfffe
mov bp, 0xfffe
; clear the screen
mov si, 0
CLEARSCREEN:
mov byte[es:si], 0
mov byte[es:si + 1], 0x0a
add si, 2
cmp si, 80 * 25 * 2
jl CLEARSCREEN
; print welcome message`
I don't understand the beginning: jmp 0x07C0:START How does it set the CS register?
And what are the two variables TOTALSECTORCOUNT and KERNEL32SECTORCOUNT for? They don't appear anywhere in the bootsector file and if I remove them, the bootloader fails to load the welcome message.
Removing the parts causes the OS to fail to load. So what is the significance of that jmp statement and the two variables?
``[ORG 0x00]
[BITS 16]
jmp START
START:
mov ax, 0x07c0
mov ds, ax ; set DS(segment register) to the address of the bootloader.
mov ax, 0xb800
mov es, ax ; set ES(segment register) to the address of the video memory starting address.
; stack initialization
mov ax, 0x0000
mov ss, ax
mov sp, 0xfffe
mov bp, 0xfffe
`
I am not great with assembly and usually use the AT&T syntax also. I have however written a bootloader before.
Hopefully you have learnt about the segmented addressing system used in 16 bit applications. The cs register holds the code segment. http://wiki.osdev.org/Segmentation
jmp 0x07C0:START ;This is a long jump
jmp segment:offset
A long jump sets the cs register to segment parameter and then does a jump to the offset parameter. When you do a short jump the cs register doesn't change. I assume that it would contain 0x0. You can use a short jump but you must tell your assembler or linker where the code will be run.
EDIT: After reading the code again there is the [org 0x00] line. This sets the cs register to 0x00 by default. If you wanted to use the short jump try changing this line to [org 0x7c00]
CS should already be set to 0x7c00 by the BIOS so the line:
jmp 0x07c0:START
can be replaced by:
jmp START
The two variables you mention must be use elsewhere in the code to load the kernel. However, it appears you haven't posted the whole code here.
Without seeing the rest of the bootsector code, we cannot help.

Resources