I have created a simple assembly program, getting the DC for the screen then releasing the DC for the screen, every once in awhile (about 1/4 of the time, sometimes less sometimes more but average 1/4) the program doesn't end and when i try to break all the program it doesn't show what code is executing, I don't know why this is happening or how i can fix it
My code that i am running on visual studio, masm assembler.
includelib user32.lib
include externals.asm
.data
.code
start proc
xor rcx, rcx
getdcfail:
call GetDC
cmp rax, 0
je getdcfail
mov r12, rax
releasedcfail:
mov rdx, r12
xor rcx, rcx
call ReleaseDC
cmp rax, 0
je releasedcfail
ret
start endp
end
here is externals.asm
extrn GetDC:proc
extrn ReleaseDC:proc
extrn GetDesktopWindow:proc
Related
I created a small project under Win64 without any _printf from standard C library (on pure WinAPI). Code of the program below:
; ------------------------------------------------------------------------------ EXTERNS
extern GetStdHandle
extern WriteConsoleW
; ------------------------------------------------------------------------------ MACROSES
%define NULL 0
%define STD_OUTPUT_HANDLE -11
; ------------------------------------------------------------------------------ PROGRAM DATA
section .bss noexecute
hStdOut resq 1
chWritten resd 1
section .data noexecute
; wchar string!
msg dw __utf16__('Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї=Ї'), 10, 0
msg.sizeof equ ($-msg)
section .rodata noexecute
; ------------------------------------------------------------------------------ PROGRAM CODE
section .text
global __main
; prologue
__main: push rbp
mov rbp, rsp
; Get hStdOut to print in console
mov rcx, STD_OUTPUT_HANDLE
call GetStdHandle
mov qword [hStdOut], rax
mov rcx, rax
mov rdx, msg
mov r8, msg.sizeof
mov r9, chWritten
push NULL
call WriteConsoleW
; epilogue
pop rbp
exit0: xor rax, rax
ret
command:
nasm -fwin64 D:\Desktop\Roberto\asm_docs\files\myprog.asm -o myprog.exe
The error is a blue window that says:
Unable to run executable on your PC. To find a version for your computer, contact to developer of the application
No warnings during the preprocessing, compilation and linking.
Tried to run with -fwin32 replacing all r- registers on e- but still no effect...
What should i do? Thanks in advance!
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
I am using visual studio for assembly coding and I am pretty new to assembly. My problem is when I assign a number to a register the value of the number is changed.
.386
.model flat, stdcall
stack 4096
ExitProcess PROTO, dwExitCode: DWORD
.data
;define your variables here
adword DWORD ?
aword WORD 7788h
.code
main PROC
mov eax,11223344h ; moved a constant into a register
mov ebx, eax ; moved ebx -> eax
mov adword, eax ; mov eax-> adword
mov ax, aword ; 7788h -> ax
mov ah, 10h
INVOKE ExitProcess, 0
main ENDP
END main
The value of Eax is not 11223344 it becomes something else.
Ok. So I have this program that attempts to create a value in the Windows registry. Unfortunately, nothing happens. I have been trying to figure out if any of the parameters are wrong. Here is the code:
includelib \Masm64\Lib\Kernel32.lib
includelib \Masm64\Lib\Advapi32.lib
extern RegOpenKeyExA : proc
extern RegSetValueExA : proc
extern ExitProcess : proc
dseg segment para 'DATA'
vlnm db 'Startup', 0
sbky db 'Software\Microsoft\Windows\CurrentVersion\Run', 0
phkr dd 0
path db 'C:\Users\School\AppData\Roaming\Startups.exe', 0
dseg ends
cseg segment para 'CODE'
start proc
lea rdx, [phkr]
push rdx
sub rsp, 28h
mov r9d, 2
xor r8d, r8d
lea rdx, [sbky]
mov ecx, 80000001h
call RegOpenKeyExA
add rsp, 28h
push 45
lea rbx, [path]
push rbx
sub rsp, 28h
mov r9d, 1
xor r8d, r8d
lea rdx, [vlnm]
mov ecx, phkr
call RegSetValueExA
call ExitProcess
start endp
cseg ends
end
Any suggestions?
Allow me to answer my own question. The problem does not truly concern incorrect parameters, but a mistake that I made allocating stack space. Whereas I was expected to allocate 20h of stack space for rcx, rdx, r8, and r9, and align the return address on a 16-byte boundary, I had mistakenly created a template as follows:
*empty* (rsp-8)
param2 (rsp-16)
param1 (rsp-24)
*empty* (rsp-32... causes incorrect parameters and convention!)
space for r9 (rsp-40)
space for r8 (rsp-48)
space for rdx (rsp-56)
space for rcx (rsp-64)
return address (rsp-72... not on a 16-byte boundary!)
The correct template would be
*empty* (rsp-8)
param2 (rsp-16)
param1 (rsp-24)
space for r9 (rsp-32)
space for r8 (rsp-40)
space for rdx (rsp-48)
space for rcx (rsp-56)
return address (rsp-64)
I had unintentionally allocated an extra 8 bytes between the stack parameters and register parameters, before the RegSetValueEx call, thus supplying an incorrect parameter. Here is the correct code:
includelib \Masm64\Lib\Kernel32.lib
includelib \Masm64\Lib\Advapi32.lib
extern RegOpenKeyExA : proc
extern RegSetValueExA : proc
extern ExitProcess : proc
dseg segment para 'DATA'
vlnm db 'Startup', 0
sbky db 'Software\Microsoft\Windows\CurrentVersion\Run', 0
phkr dd 0
path db 'C:\Users\Games\AppData\Roaming\Startups.exe', 0
dseg ends
cseg segment para 'CODE'
start proc
lea rdx, [phky]
push rdx
sub rsp, 20h
mov r9d, 2
xor r8d, r8d
lea rdx, [sbky]
mov ecx, 80000001h
call RegOpenKeyExA
add rsp, 20h
push 44
lea rbx, [path]
push rbx
sub rsp, 20h
mov r9d, 1
xor r8, r8
lea rdx, [vlnm]
mov ecx, phkr
call RegSetValueExA
fini: call ExitProcess
start endp
cseg ends
end
Cheers!
You're only allocating 2 bytes for your key (phkr dw 0). It seems to me like it should be at least 4 bytes.
Apart from that, I suggest that you add some error checks. Both RegOpenKeyEx and RegSetValueEx return non-zero error codes if they fail.
I assumed I had push'ed something without popping it, or vice versa, but I can't find anything wrong! I write to the console with a call to a dll that links properly, and I inexplicably am in no mans land... (address 0x0000000000000000)
I've put some sleeps in, and I'm sure that the api call WriteConsoleA is returning. It's on my last ret under the print function.
Any ideas?
.exe:
extern FreeConsole
extern Sleep
extern ExitProcess
extern print
extern newconsole
extern strlen
section .data BITS 64
title: db 'Consolas!',0
message: db 'Hello, world',0,0
section .text bits 64
global Start
Start:
mov rcx, title
call newconsole
mov rcx, 1000
call Sleep
mov rcx, message
call print
mov rcx, 10000
call Sleep
call FreeConsole
xor rcx, rcx
call ExitProcess
.dll:
extern AllocConsole
extern SetConsoleTitleA
extern GetStdHandle
extern WriteConsoleA
extern Sleep
export newconsole
export strlen
export print
section .data BITS 64
console.writehandle: dq 0
console.readhandle: dq 0
console.write.result: dq 0
section .text BITS 64
global strlen
strlen:
push rax
push rdx
push rdi
mov rdi, rcx
xor rax, rax
mov rcx, dword -1
cld
repnz scasb
neg rcx
sub rcx, 2
pop rdi
pop rdx
pop rax
ret
global print
print:
mov rbp, rsp
push rcx
call strlen
mov r8, rcx
pop rdx
mov rcx, [console.writehandle]
mov r9, console.write.result
push qword 0
call WriteConsoleA
ret
global newconsole
newconsole:
push rax
push rcx
call AllocConsole
pop rcx
call SetConsoleTitleA
mov rcx, -11
call GetStdHandle
mov [console.writehandle], rax
pop rax
ret
I assume you're talking about this function:
global print
print:
mov rbp, rsp
push rcx
call strlen
mov r8, rcx
pop rdx
mov rcx, [console.writehandle]
mov r9, console.write.result
push qword 0
call WriteConsoleA
ret
The x64 ABI requires that stack space is reserved even for parameters passed in registers. WriteConsoleA is free to use those stack locations for whatever it wants - so you need to make sure that you've adjusted the stack appropriately. As it stands, you're pushing only the last reserved pointer parameter. I think something like the following will do the trick for you:
push qword 0
sub rsp, 4 * 8 // reserve stack for register parameters
call WriteConsoleA
mov rsp, rbp // restore rsp
ret
See http://msdn.microsoft.com/en-us/library/ms235286.aspx (emphasis added):
The x64 Application Binary Interface (ABI) is a 4 register fast-call calling convention, with stack-backing for those registers.
...
The caller is responsible for allocating space for parameters to the callee, and must always allocate sufficient space for the 4 register parameters, even if the callee doesn’t have that many parameters.
According to calling convention, you have to clean up arguments you put on the stack. In this case that applies to the 5th argument to WriteConsoleA. Since you have a copy of original rsp in rbp, you can reload rsp from rbp, or just add 8 after the call.