How to obtain the VSync Display refresh pulse in Linux? - linux

I'm programming some routines on a Linux NASM x86-64 asm code.
How can I obtain the pulse of the display refresh, VSync?
I guess maybe via syscall I can reach the pulse, but I accept other suggestions, don't ask me why, i really need the pulse to avoid Flicker on display.
I know how to do it for windows as shown in code below, but Linux doesn't support D3D.
;;;;; WINDOWS VERSION EXAMPLE!
;ENABLE VSYNC
Therraszeta3:
CMP BYTE [RY_X+0x1003],255
jnz .L1232321
mov rcx,0
mov rax, [GetDC__]
mov [D3DKMT_OPENADAPTERFROMHDC_hDc], rax
lea rcx, [D3DKMT_OPENADAPTERFROMHDC]
call [GetProcAddress_LoadLibrary_Gdi32_dll_D3DKMTOpenAdapterFromHdc_]
mov [D3DKMTOpenAdapterFromHdc__], rax
;;
mov eax, dword [D3DKMT_OPENADAPTERFROMHDC_hAdapter]
mov dword [D3DKMT_WAITFORVERTICALBLANKEVENT_hAdapter], eax
mov dword [D3DKMT_WAITFORVERTICALBLANKEVENT_hDevice],0
mov eax, dword [D3DKMT_OPENADAPTERFROMHDC_VidPnSourceId]
mov dword [D3DKMT_WAITFORVERTICALBLANKEVENT_VidPnSourceId], eax
lea rcx, [D3DKMT_WAITFORVERTICALBLANKEVENT]
call [GetProcAddress_LoadLibrary_Gdi32_dll_D3DKMTWaitForVerticalBlankEvent_]
mov [D3DKMTWaitForVerticalBlankEvent__], rax
.L1232321
;;;;;
I expect to obtain the pulse in an infinite loop, indicating the beginning of every frame.

Related

Assembly Language nasm error

I have written the following assembly code as prescribed by my text book in the intel 64 bit syntax
Section .text
global _short
_start:
jmp short Gotocall
shellcode:
pop rcx
xor eax,eax
mov byte [rcx+8], al
lea rdi, [rax]
mov long [rcx+8], rdi
mov long [rcx+12], eax
mov byte al, 0x3b
mov rsi, rax
lea rdi, [esi+8]
lea edx, [esi+12]
int 0x80
Gotocall:
call shellcode
db '/bin/shJAAAAKKKK'
but i get a nasm error in line 10 like this
asmshell.asm:10: error: mismatch in operand sizes
Can anybody tell me what mistake is their in my code.
And can anybody please tell me some good references to the 64 bit intel assembly instructions.
If you mean the error is on line 10
mov long [rcx+8], rdi
I was about to ask you what size long qualifier is, but the next line
mov long [rcx+12], eax
shows that you are moving two different sizes of register to the same size destination. In the first case the 64-bit register rdi, in the second case the 32-bit register eax, and long cannot satisfy them both.
Why not just drop the long since by specifying the register, the assembler knows the size of the destination? But sadly, you have only allowed 4 bytes memory to store a 64-bit register, given away by the [rcx+8] followed by [rcx+12].
Perhaps you intended
mov long [rcx+8], edi

I'm getting a segmentation fault in my assembly program [duplicate]

The tutorial I am following is for x86 and was written using 32-bit assembly, I'm trying to follow along while learning x64 assembly in the process. This has been going very well up until this lesson where I have the following simple program which simply tries to modify a single character in a string; it compiles fine but segfaults when ran.
section .text
global _start ; Declare global entry oint for ld
_start:
jmp short message ; Jump to where or message is at so we can do a call to push the address onto the stack
code:
xor rax, rax ; Clean up the registers
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx
; Try to change the N to a space
pop rsi ; Get address from stack
mov al, 0x20 ; Load 0x20 into RAX
mov [rsi], al; Why segfault?
xor rax, rax; Clear again
; write(rdi, rsi, rdx) = write(file_descriptor, buffer, length)
mov al, 0x01 ; write the command for 64bit Syscall Write (0x01) into the lower 8 bits of RAX
mov rdi, rax ; First Paramter, RDI = 0x01 which is STDOUT, we move rax to ensure the upper 56 bits of RDI are zero
;pop rsi ; Second Parameter, RSI = Popped address of message from stack
mov dl, 25 ; Third Parameter, RDX = Length of message
syscall ; Call Write
; exit(rdi) = exit(return value)
xor rax, rax ; write returns # of bytes written in rax, need to clean it up again
add rax, 0x3C ; 64bit syscall exit is 0x3C
xor rdi, rdi ; Return value is in rdi (First parameter), zero it to return 0
syscall ; Call Exit
message:
call code ; Pushes the address of the string onto the stack
db 'AAAABBBNAAAAAAAABBBBBBBB',0x0A
This culprit is this line:
mov [rsi], al; Why segfault?
If I comment it out, then the program runs fine, outputting the message 'AAAABBBNAAAAAAAABBBBBBBB', why can't I modify the string?
The authors code is the following:
global _start
_start:
jmp short ender
starter:
pop ebx ;get the address of the string
xor eax, eax
mov al, 0x20
mov [ebx+7], al ;put a NULL where the N is in the string
mov al, 4 ;syscall write
mov bl, 1 ;stdout is 1
pop ecx ;get the address of the string from the stack
mov dl, 25 ;length of the string
int 0x80
xor eax, eax
mov al, 1 ;exit the shellcode
xor ebx,ebx
int 0x80
ender:
call starter
db 'AAAABBBNAAAAAAAABBBBBBBB'0x0A
And I've compiled that using:
nasm -f elf <infile> -o <outfile>
ld -m elf_i386 <infile> -o <outfile>
But even that causes a segfault, images on the page show it working properly and changing the N into a space, however I seem to be stuck in segfault land :( Google isn't really being helpful in this case, and so I turn to you stackoverflow, any pointers (no pun intended!) would be appreciated
I would assume it's because you're trying to access data that is in the .text section. Usually you're not allowed to write to code segment for security. Modifiable data should be in the .data section. (Or .bss if zero-initialized.)
For actual shellcode, where you don't want to use a separate section, see Segfault when writing to string allocated by db [assembly] for alternate workarounds.
Also I would never suggest using the side effects of call pushing the address after it to the stack to get a pointer to data following it, except for shellcode.
This is a common trick in shellcode (which must be position-independent); 32-bit mode needs a call to get EIP somehow. The call must have a backwards displacement to avoid 00 bytes in the machine code, so putting the call somewhere that creates a "return" address you specifically want saves an add or lea.
Even in 64-bit code where RIP-relative addressing is possible, jmp / call / pop is about as compact as jumping over the string for a RIP-relative LEA with a negative displacement.
Outside of the shellcode / constrained-machine-code use case, it's a terrible idea and you should just lea reg, [rel buf] like a normal person with the data in .data and the code in .text. (Or read-only data in .rodata.) This way you're not trying execute code next to data, or put data next to code.
(Code-injection vulnerabilities that allow shellcode already imply the existence of a page with write and exec permission, but normal processes from modern toolchains don't have any W+X pages unless you do something to make that happen. W^X is a good security feature for this reason, so normal toolchain security features / defaults must be defeated to test shellcode.)

8086 qemu my own keyboard interrupt handler

I am trying to write a bootloader which is just a program that sets its own keybord interrupt handler and handles keyboard presses.
However I am lost.
This one does not respond to keyboard presses by writing to video RAM.
org 7c00h ; BOOT PROGRAM
mov ax,03h
int 10h ; 80x25 video mode
mov ax,1112h;
int 10h ; 80x50 video mode
cli ; Zakaz preruseni
mov word[ds:20h],keyboard_handler ; nastaveni INT9 na moji funkci
mov word[ds:22h],0h
sti
jmp $
keyboard_handler:
cli
push ax
push dx
push bx
in al,60h
mov dx,0b800h
mov es,dx
mov dx,0000h
mov ds,dx
mov dl,10h
div dl; al+ah
add ax,3030h
mov dl,ah
cmp al,3ah
jl not_add
add al,7h
not_add cmp dl,3ah
jl not_add2
add dl,7h
not_add2 mov ah,21h
mov dh,21h
mov bx,[ds:vidoff]
mov word[es:bx],ax
add bx,2h
mov word[es:bx],dx
add bx,2h
mov word[ds:vidoff],bx
;finalizing code
mov al,20h
out 20h,al ;odhlaseni preruseni
;mov word ax,[ds:22h]
;mov cs,ax
;mov ds,ax
;mov ss,ax
;mov es,ax
pop bx
pop dx
pop ax
sti
iret
vidoff dw 0FF0h
times 510-($-$$) db 0
dw 0AA55h
And this one is messy, but it keeps writing to video RAM eventhough no key was pressed. If I press a key, however, at least it responds to my keypress by taking my scancode and writing to video RAM accordingly. Then it again continues as if some key was pressed continously.
org 7c00h ; BOOT PROGRAM
;++++++ Nastaveni video mode 80x50 a INT9(co reaguje na klavesnici pomoci preruseni IRQ1)
mov ax,03h
int 10h ; 80x25 video mode
mov ax,1112h;
int 10h ; 80x50 video mode
mov dx,0b800h
mov es,dx
mov dx,0h
mov ds,dx
mov di,0FF0h
mov bx,0h
mov ds,bx
cli ; Zakaz preruseni
mov word[ds:20h],keyboard_handler ; nastaveni INT9 na moji funkci
mov word[ds:22h],0h
sti
; Povoleni preruseni
jmp $
keyboard_handler:
push es
push ax
mov ax,0h
in al,60h
mov ch,10h
div ch
mov byte[prvni_cislice],al
mov byte[druha_cislice],ah
mov ch,al
mov cl,0dbh
mov word[barva_cislice],cx
mov bl,ah
mov bh,0dbh
cmp cx,bx
jne normal
xor ch,0fh
mov bh,ch
normal mov word[barva_podkladu],bx
mov word[es:di],bx
add di,2h
mov al,20h
out 20h,al ;odhlaseni preruseni
pop ax
pop es
iret
;hexacislice
prvni_cislice db 0h
druha_cislice db 0h
;hotove znaky
barva_podkladu dw 0h
barva_cislice dw 0h
offset_radku dw 0h
PRNGseed dw 0h
times 510-($-$$) db 0
dw 0AA55h
What I am doing wrong? Am I forgetting something? In some other code I saw somebody adding out,61h or something like that, I dont know what that does though.
The biggest problem with these programs is that you are NOT setting up the keyboard interrupt! Instead you are messing with the system timer interrupt.
mov word[ds:20h],keyboard_handler ; nastaveni INT9 na moji funkci
mov word[ds:22h],0h
Better use this :
mov word[ds:24h],keyboard_handler
mov word[ds:26h],0h
The rest of the code you've written poses a real challenge to people that do not speak your native language. Please use English-only names for labels and variables.
Also be generous with comments in your code. They make reading a lot easier and thus increase your chance of getting an answer.

Conditional jump fails in linux x86 intel syntax(NASM)

STORY(IM A NEWBIE):
I started reading a pdf tutorial about programming in assembly(x86 intel) using the famous nasm assembler and i have a problem executing a very basic assembly code(inspired by a code about loops from the tutorial).
THE PROBLEM(JE FAILS):
This assembly code should read a digit(a character(that means '0'+digit)) from stdin and then write to the screen digit times "Hello world\n".Really easy loop :decrease digit and if digit equals zero('0' not the integer the character) jump(je) to the exit(mov eax,1\nint 0x80).
Sounds really easy but when i try to execute the output is weird.(really weird and BIG)
It runs many times throught the loop and stops when digit equals '0'(weird because until the program stops the condition digit == '0' been tested many times and it should be true)
Actually my problem is that the code fails to jump when digit == '0'
THE CODE(IS BIG):
segment .text
global _start
_start:
;Print 'Input a digit:'.
mov eax,4
mov ebx,1
mov ecx,msg1
mov edx,len1
int 0x80
;Input the digit.
mov eax,3
mov ebx,0
mov ecx,dig
mov edx,2
int 0x80
;Mov the first byte(the digit) in the ecx register.
;mov ecx,0
mov ecx,[dig]
;Use ecx to loop dig[0]-'0' times.
loop:
mov [dig],ecx
mov eax,4
mov ebx,1
mov ecx,dig
mov edx,1
int 0x80
mov eax,4
mov ebx,1
mov ecx,Hello
mov edx,Hellolen
int 0x80
;For some debuging (make the loop stop until return pressed)
;mov eax,3
;mov ebx,0
;mov ecx,some
;mov edx,2
;int 0x80
;Just move dig[0](some like character '4' or '7') to ecx register and compare ecx with character '0'.
mov ecx,[dig]
dec ecx
cmp ecx,'0'
;If comparison says ecx and '0' are equal jump to exit(to end the loop)
je exit
;If not jump back to loop
jmp loop
;Other stuff ...(like an exit procedure and a data(data,bss) segment)
exit:
mov eax,1
int 0x80
segment .data
msg1 db "Input a digit:"
len1 equ $-msg1
Hello db ":Hello world",0xa
Hellolen equ $-Hello
segment .bss
dig resb 2
some resb 2
THE OUTPUT:
Input a digit:4
4:Hello world
3:Hello world
2:Hello world
1:Hello world
0:Hello world
...
...(many loops later)
...
5:Hello world
4:Hello world
3:Hello world
2:Hello world
1:Hello world
$
That is my question:What is wrong with this code?
Could you explain that ?
AND i dont need alternative codes that will magically(without explanation) run cause i try to learn(im a newbie)
That is my problem(and my first question in Stackoverflow.com )
ECX is 32 bit, a character is just 8 bit. Use a 8 bit register, such as CL instead of ECX.
As jester mentioned, ecx comes in as a character so you probably should use cl
loop:
mov [dig],cl
...
mov cl,[dig]
dec cl
cmp cl,'0'
jne loop
You can also load ecx with movzx which clears the top bits of the register (i.e. a zero-extedning load):
...
movzx ecx, byte [dig]
loop:
mov [dig], cl ; store just the low byte, if you want to store
...
movzx ecx, byte [dig]
dec ecx
cmp ecx, '0'
jne loop
Note that it is often suggested that you do not use the al, bl, cl, dl registers as their use is not fully optimized. Whether this is still true, I do not know.

x64 bit assembly

I started assembly (nasm) programming not too long ago. Now I made a C function with assembly implementation which prints an integer. I got it working using the extended registers, but when I want to write it with the x64 registers (rax, rbx, ..) my implementation fails. Does any of you see what I missed?
main.c:
#include <stdio.h>
extern void printnum(int i);
int main(void)
{
printnum(8);
printnum(256);
return 0;
}
32 bit version:
; main.c: http://pastebin.com/f6wEvwTq
; nasm -f elf32 -o printnum.o printnum.asm
; gcc -o printnum printnum.o main.c -m32
section .data
_nl db 0x0A
nlLen equ $ - _nl
section .text
global printnum
printnum:
enter 0,0
mov eax, [ebp+8]
xor ebx, ebx
xor ecx, ecx
xor edx, edx
push ebx
mov ebx, 10
startLoop:
idiv ebx
add edx, 0x30
push dx ; With an odd number of digits this will screw up the stack, but that's ok
; because we'll reset the stack at the end of this function anyway.
; Needs fixing though.
inc ecx
xor edx, edx
cmp eax, 0
jne startLoop
push ecx
imul ecx, 2
mov edx, ecx
mov eax, 4 ; Prints the string (from stack) to screen
mov ebx, 1
mov ecx, esp
add ecx, 4
int 80h
mov eax, 4 ; Prints a new line
mov ebx, 1
mov ecx, _nl
mov edx, nlLen
int 80h
pop eax ; returns the ammount of used characters
leave
ret
x64 version:
; main.c : http://pastebin.com/f6wEvwTq
; nasm -f elf64 -o object/printnum.o printnum.asm
; gcc -o bin/printnum object/printnum.o main.c -m64
section .data
_nl db 0x0A
nlLen equ $ - _nl
section .text
global printnum
printnum:
enter 0, 0
mov rax, [rbp + 8] ; Get the function args from the stac
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx
push rbx ; The 0 byte of the string
mov rbx, 10 ; Dividor
startLoop:
idiv rbx ; modulo is in rdx
add rdx, 0x30
push dx
inc rcx ; increase the loop variable
xor rdx, rdx ; resetting the modulo
cmp rax, 0
jne startLoop
push rcx ; push the counter on the stack
imul rcx, 2
mov rdx, rcx ; string length
mov rax, 4
mov rbx, 1
mov rcx, rsp ; the string
add rcx, 4
int 0x80
mov rax, 4
mov rbx, 1
mov rcx, _nl
mov rdx, nlLen
int 0x80
pop rax
leave
ret ; return to the C routine
Thanks in advance!
I think your problem is that you're trying to use the 32-bit calling conventions in 64-bit mode. That won't fly, not if you're calling these assembly routines from C. The 64-bit calling convention is documented here: http://www.x86-64.org/documentation/abi.pdf
Also, don't open-code system calls. Call the wrappers in the C library. That way errno gets set properly, you take advantage of sysenter/syscall, you don't have to deal with the differences between the normal calling convention and the system-call argument convention, and you're insulated from certain low-level ABI issues. (Another of your problems is that write is system call number 1, not 4, for Linux/x86-64.)
Editorial aside: There are two, and only two, reasons to write anything in assembly nowadays:
You are writing one of the very few remaining bits of deep magic that cannot be written in C alone (a good example is the guts of libffi)
You are hand-optimizing an inner-loop subroutine that has been measured to be performance-critical and the C compiler doesn't do a good enough job on.
Otherwise just write whatever it is in C. Your successors will thank you.
EDIT: checked system call numbers.
I'm not sure if this answer is related to the problem you're seeing (since you didn't specify anything about what the failure is), but 64-bit code has a different calling convention than 32-bit code does. Both of the major 64-bit Intel ABIs (Windows & Linux/BSD/Mac OS) pass function parameters in registers and not on the stack. Your program appears to still be expecting them on the stack, which isn't the normal way to go about it.
Edit: Now that I see there is a C main() routine that calls your functions, my answer is exactly about the problem you're having.

Resources