I'm happy to report that i have coded again, although a very simple program, but it was fun as always has been. This little console program will show in the console window the values of the general purpose registers before the execution of the first instruction of the program. You exit the program by pressing ENTER (intro, return, etc), or you can just close the console window.
I attach the source, the .exe and a bat file with the simple commands to assemble and run. But for this .bat file to work, you will have to run it in the same path as ml64. You can do all the changes you need/want to all this stuff (including, of course, the code).
It will be good if at least someone gives feedback about other ideas to show the values of the registers, since after thinking for a while, i only got the idea of processing each nibble (nibble by nibble). Don't know if that's the standard way to do it or the slowest one... :toothy:
Btw, i have changed my style of indentation by using no indentation whatsoever, hopefully that doesn't turn anyone crazy... :mrgreen:
Hi felipe,
Code works fine but the left aligned code I find really hard to read.
Sorry Hutch i will change that at other time. By now i have fixed a little bug (i was showing the pushed registers 1 qword displaced). I fixed the error in this attachment.
Now works all fine.
here is what the program shows in my computer:
This are the values of the general purpose registers
before the execution of the first instruction of this program.
Press RETURN to exit the program...
RAX: 0000000000000000
RBX: 00007FF6B8F01000
RCX: 00007FF6B8DEF000
RDX: 00007FF6B8F01000
RSI: 00007FF6B8DEF000
RDI: 00007FF6B8DEF000
RBP: 0000000000000000
RSP: 000000978765FC28
R8: 00007FF6B8DEF000
R9: 0000000000000000
R10: 0000000000000000
R11: 0000000000000000
R12: 0000000000000000
R13: 0000000000000000
R14: 0000000000000000
R15: 0000000000000000
And below (hopefully you can see it) there's an image of what the debugger shows in the registers at the entry point of the program.
Quote from: felipe on May 25, 2022, 12:32:30 PM
Sorry Hutch i will change that at other time. By now i have fixed a little bug (i was showing the pushed registers 1 qword displaced). I fixed the error in this attachment.
C:\Masm32\Members\Felipe>ml64 /c registers.asm
"ml64" non è riconosciuto come comando interno o esterno,
un programma eseguibile o un file batch.
C:\Masm32\Members\Felipe>link /subsystem:console /entry:start registers.obj
"link" non è riconosciuto come comando interno o esterno,
un programma eseguibile o un file batch.
Apparently you rely on environment variables :sad:
This works better:
\Masm64\bin\ml64 /c registers.asm
\Masm64\bin\link /subsystem:console /entry:start registers.obj
registers.exe
RAX: 0000000077065560
RBX: 0000000000000000
RCX: 000007FFFFFDF000
RDX: 000000013FC61000
RSI: 0000000000000000
RDI: 0000000000000000
RBP: 0000000000000000
RSP: 000000000025F948
R8: 000007FFFFFDF000
R9: 000000013FC61000
R10: 0000000000000000
R11: 0000000000000000
R12: 0000000000000000
R13: 0000000000000000
R14: 0000000000000000
R15: 0000000000000000
For comparison, using deb (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1019):
x:rax 1234567890abcdefh
x:rbx 1400022b0h
x:rcx 0h
x:rdx 0h
x:rsi 0h
x:rdi 0h
x:rbp 12ff50h
x:rsp 12fed0h
x:r8 12fd48h
x:r9 12ff50h
x:r10 335040h
x:r11 12fb22h
x:r12 0h
x:r13 0h
x:r14 0h
x:r15 0h
This program was assembled with ml64 in 64-bit format.
The reason for differences is that there are some initialisation routines before
deb starts working.
My debugger shows this on entry point (compare to your
rsp, rsi, rdi!):
There are different ways of doing this in 64 bit. I use a technique for the accessory "livedb.exe".
@jj2007 aside the problem with the .bat file, i don't get clear what are you pointing. Would you be more explicit please?
Here's the code with a more classic indentation (also attached):
; Program that shows general purpose registers values.
option casemap:none
include /masm32/include64/win64.inc
include /masm32/include64/kernel32.inc
includelib /masm32/lib64/kernel32.lib
.data
rax_reg byte "RAX: ", 16 dup(0h),0dh,0ah
rbx_reg byte "RBX: ", 16 dup(0h),0dh,0ah
rcx_reg byte "RCX: ", 16 dup(0h),0dh,0ah
rdx_reg byte "RDX: ", 16 dup(0h),0dh,0ah
rsi_reg byte "RSI: ", 16 dup(0h),0dh,0ah
rdi_reg byte "RDI: ", 16 dup(0h),0dh,0ah
rbp_reg byte "RBP: ", 16 dup(0h),0dh,0ah
rsp_reg byte "RSP: ", 16 dup(0h),0dh,0ah
r8_reg byte "R8: ", 16 dup(0h),0dh,0ah
r9_reg byte "R9: ", 16 dup(0h),0dh,0ah
r10_reg byte "R10: ", 16 dup(0h),0dh,0ah
r11_reg byte "R11: ", 16 dup(0h),0dh,0ah
r12_reg byte "R12: ", 16 dup(0h),0dh,0ah
r13_reg byte "R13: ", 16 dup(0h),0dh,0ah
r14_reg byte "R14: ", 16 dup(0h),0dh,0ah
r15_reg byte "R15: ", 16 dup(0h)
con_title byte "GENERAL PURPOSE REGISTERS VALUES",0h
info_text byte "This are the values of the general purpose registers",0ah,0dh, "before the execution of the first instruction of this program.",0ah,0dh, \
"Press RETURN to exit the program...",0dh,0ah,0dh,0ah
input_buff qword 0h
chars_written qword 0h
chars_readed qword 0h
.code
start proc
push rsp
push rcx
push rdx
push r8
push r9
sub rsp,30h
mov rcx,rax
lea rdx,rax_reg
mov r8,sizeof rax_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rax.
mov rcx,rbx
lea rdx,rbx_reg
mov r8,sizeof rbx_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rbx.
mov rcx,rsi
lea rdx,rsi_reg
mov r8,sizeof rsi_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rsi.
mov rcx,rdi
lea rdx,rdi_reg
mov r8,sizeof rdi_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rdi.
mov rcx,r15
lea rdx,r15_reg
mov r8,sizeof r15_reg
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r15.
mov rcx,r14
lea rdx,r14_reg
mov r8,sizeof r14_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r14.
mov rcx,r13
lea rdx,r13_reg
mov r8,sizeof r13_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r13.
mov rcx,r12
lea rdx,r12_reg
mov r8,sizeof r12_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r12.
mov rcx,r11
lea rdx,r11_reg
mov r8,sizeof r11_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r11.
mov rcx,r10
lea rdx,r10_reg
mov r8,sizeof r10_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r10.
mov rcx,rbp
lea rdx,rbp_reg
mov r8,sizeof rbp_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rbp.
mov rcx,[rsp+30h]
lea rdx,r9_reg
mov r8,sizeof r9_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r9.
mov rcx,[rsp+38h]
lea rdx,r8_reg
mov r8,sizeof r8_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of r8.
mov rcx,[rsp+40h]
lea rdx,rdx_reg
mov r8,sizeof rdx_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rdx.
mov rcx,[rsp+48h]
lea rdx,rcx_reg
mov r8,sizeof rcx_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rcx.
mov rcx,[rsp+50h]
lea rdx,rsp_reg
mov r8,sizeof rsp_reg
sub r8,2 ; Discard 0dh and 0ah.
mov r9,16 ; 16 nibbles.
call reg_value ; Get value of rsp.
call FreeConsole ; Detach process of inherited console
call AllocConsole ; and create a new one.
lea rcx,con_title
call SetConsoleTitle
mov rcx,STD_OUTPUT_HANDLE
call GetStdHandle
mov r15,rax ; Output handle.
mov rcx,r15
lea rdx,info_text
mov r8,sizeof info_text
lea r9,chars_written
mov qword ptr[rsp+20h],NULL
call WriteConsole
mov rcx,r15 ; Output handle.
lea rdx,rax_reg
mov r8,sizeof rax_reg
add r8,sizeof rbx_reg
add r8,sizeof rsi_reg
add r8,sizeof rdi_reg
add r8,sizeof rcx_reg
add r8,sizeof rdx_reg
add r8,sizeof rsp_reg
add r8,sizeof rbp_reg
add r8,sizeof r8_reg
add r8,sizeof r9_reg
add r8,sizeof r10_reg
add r8,sizeof r11_reg
add r8,sizeof r12_reg
add r8,sizeof r13_reg
add r8,sizeof r14_reg
add r8,sizeof r15_reg
lea r9,chars_written
mov qword ptr[rsp+20h],NULL
call WriteConsole
mov rcx,STD_INPUT_HANDLE
call GetStdHandle
mov r15,rax ; Input handle.
mov rcx,r15
mov rdx,ENABLE_LINE_INPUT
call SetConsoleMode
mov rcx,r15
lea rdx,input_buff
mov r8,1 ; Read just the character CR.
lea r9,chars_readed
mov qword ptr[rsp+20h],NULL
call ReadConsole
xor rcx,rcx
call ExitProcess
start endp
reg_value proc
push rbp
mov rbp,rsp
next_nibble:
mov rsp,rcx
and rcx,0fh ; Isolate lsb.
cmp rcx,09h
ja can_be_a
or rcx,30h ; To ascii.
dec r8
mov [rdx+r8],cl
dec r9
and r9,r9
jz all_done
mov rcx,rsp
shr rcx,4
jmp next_nibble
can_be_a:
cmp rcx,0ah
jne can_be_b
mov rcx,'A'
dec r8
mov [rdx+r8],cl
dec r9
and r9,r9
jz all_done
mov rcx,rsp
shr rcx,4
jmp next_nibble
can_be_b:
cmp rcx,0bh
jne can_be_c
mov rcx,'B'
dec r8
mov [rdx+r8],cl
dec r9
and r9,r9
jz all_done
mov rcx,rsp
shr rcx,4
jmp next_nibble
can_be_c:
cmp rcx,0ch
jne can_be_d
mov rcx,'C'
dec r8
mov [rdx+r8],cl
dec r9
and r9,r9
jz all_done
mov rcx,rsp
shr rcx,4
jmp next_nibble
can_be_d:
cmp rcx,0dh
jne can_be_e
mov rcx,'D'
dec r8
mov [rdx+r8],cl
dec r9
and r9,r9
jz all_done
mov rcx,rsp
shr rcx,4
jmp next_nibble
can_be_e:
cmp rcx,0eh
jne is_f
mov rcx,'E'
dec r8
mov [rdx+r8],cl
dec r9
and r9,r9
jz all_done
mov rcx,rsp
shr rcx,4
jmp next_nibble
is_f:
mov rcx,'F'
dec r8
mov [rdx+r8],cl
dec r9
and r9,r9
jz all_done
mov rcx,rsp
shr rcx,4
jmp next_nibble
all_done:
mov rsp,rbp
pop rbp
ret
reg_value endp
end
Here is the output with other debbuger of the registers values in the entry point of the program (in the image below) and here is the same output in the program while it's running under this debugger:
This are the values of the general purpose registers
before the execution of the first instruction of this program.
Press RETURN to exit the program...
RAX: 0000000000000000
RBX: 00007FF640491000
RCX: 00007FF63F9CF000
RDX: 00007FF640491000
RSI: 00007FF63F9CF000
RDI: 00007FF63F9CF000
RBP: 0000000000000000
RSP: 000000DF6839FD88
R8: 00007FF63F9CF000
R9: 0000000000000000
R10: 0000000000000000
R11: 0000000000000000
R12: 0000000000000000
R13: 0000000000000000
R14: 0000000000000000
R15: 0000000000000000
Again are the same, the little bug from yesterday was fixed, the program its working well. But you are welcome to point out the opposite (with arguments). :bgrin:
Quote from: felipe on May 25, 2022, 09:35:46 PM
@jj2007 aside the problem with the .bat file, i don't get clear what are you pointing. Would you be more explicit please?
Nothing in particular, your program works fine :thumbsup:
Just keep in mind that not everybody uses environment variables (they are relict from DOS times). Both the Masm32 and Masm64 SDKs have one fine feature: they reside at the root, at
\Masmxx\
So you don't need environment variables. This will work fine:
\Masm64\bin\ml64 /c registers.asm
\Masm64\bin\link /subsystem:console /entry:start registers.obj
However, I see that you are using this:
include /masm32/include64/win64.inc
include /masm32/include64/kernel32.inc
includelib /masm32/lib64/kernel32.lib
Did you get the latest Masm64 SDK? If so, why didn't you install it to its default directory, i.e. \Masm64?
I'm not sure about the use of /forward/slashes, but they are about as common as code with no indentation :cool:
That's weird, last time i remember, to use the masm64 sdk it has to be installed in a folder named masm32. ¿Did that changed with an updated version? If that's the case, please give me a link to the lastest version. About the slashes you are right, that's a problem that comes with the amount of time from my last program. I will remember it.
Btw, i'm not using environment variables by my own, the console of the build tools (from microsoft) set them, i think with a file named vcvarsall.bat.
Last but not least, thanks to all who tried (hopefully) the last/correct version. :thup:
About the link, i think i have found it, thanks. :thup:
Hi felipe,
The earlier version while I was developing the SDK was attached to the MASM32 installation but the later version is MASM64 which is 64 bit only. I will have another version done shortly which is a lot more complete. I am currently working on a 64 bit editor which I have up and running but to replace QE will take a lot more work. QE is set up to work with the 64 bit SDK and apart from getting a few of the menu items working correctly, its very reliable.
Thanks a lot Hutch :thup:
great work felipe :thumbsup:
just wonder if I get different register values depending on it is run directly after linker or use a .bat file that starts it after another program?
or it is the windows .bat file handler registers after?
@daydreamer it's likely that the values of the registers are not always the same, that is you can get different values in different runs of the program. Windows still controls the hardware.
curious on fpu and xmm regs I wrote this,notice difference seem like been aftected by earlier stack frame,ran it from qeditor and direct click on .exe
before and after run program now
added EFLAGS and fpu status word and fpu control word
mine shows rounding to real8,while raymonds tutorial says initally real10
windows change that ?
registers
eax 75419191
ebx 7FFDE000
ecx 00000000
edx 00401000
esi 00000000
edi 00000000
esp 0018FF90
ebp 0018FF98
st0 000000000000000000000000
st1 000000000000000000000000
st2 000000000000000000000000
st3 000000000000000000000000
st4 000000000000000000000000
st5 000000000000000000000000
st6 000000000000000000000000
st7 000000000000000000000000
XMM0 00000000 00000000 00000000 00000000
XMM1 00000000 00000000 00000000 00000000
XMM2 00000000 00000000 00000000 00000000
XMM3 00000000 00000000 00000000 00000000
XMM4 00000000 00000000 00000000 00000000
XMM5 00000000 00000000 00000000 00000000
XMM6 00000000 00000000 00000000 00000000
XMM7 00000000 00000000 00000000 00000000
EFLAGS 00000007
carry clear parity clear Aux. Carry clear ZF zero clear SF Sign clear TF Trap cl
ear IF interrupt set DF Direction clear OF Overflow clear fpu control word
00000000
carry clear parity clear ZF zero clear
fpu control word
53 bits REAL8
round to nearest
registers after run program
registers
eax 00000002
ebx 004020A0
ecx 75A1D371
edx 0018FF38
esi 00000000
edi 00000000
esp 0018FF8C
ebp 0018FF98
st0 000000000000000000000000
st1 000000000000000000000000
st2 000000000000000000000000
st3 000000000000000000000000
st4 000000000000000000000000
st5 000000000000000000000000
st6 000000000000000000000000
st7 000000000000000000000000
XMM0 00000000 00000000 00000000 00000000
XMM1 00000000 00000000 00000000 00000000
XMM2 00000000 00000000 00000000 00000000
XMM3 00000000 00000000 00000000 00000000
XMM4 00000000 00000000 00000000 00000000
XMM5 00000000 00000000 00000000 00000000
XMM6 00000000 00000000 00000000 00000000
XMM7 00000000 00000000 00000000 00000000
EFLAGS 00000007
carry clear parity clear Aux. Carry clear ZF zero clear SF Sign clear TF Trap cl
ear IF interrupt set DF Direction clear OF Overflow clear fpu control word
00000000
carry clear parity clear ZF zero clear
fpu control word
53 bits REAL8
round to nearest
Press any key to continue ...
Your program works fine :thumbsup:
Have a look at fsave+frstor (http://masm32.com/board/index.php?topic=10096.0)
updated with showing EFLAGS,fpu status word,fpu control word
does everyone get the round to REAL8?probably for CPP double usage