How can I access the system time using NASM, on Linux?
(Editor's note: the accepted answer is for 16-bit DOS with direct hardware access; it would work inside DOSBox. The other answers are actually for Linux.)
Using 32-bit code under Linux:
mov eax, 13 ; call number = __NR_time
xor ebx, ebx ; tloc = NULL
int 0x80
; 32-bit time_t in EAX
This is a system call to time(2) (system call number 13), and it returns the signed 32-bit time_t in EAX.
(Unlike other system calls, return values >= -4095U (MAX_ERRNO) are still successes, and simply small negative numbers that represent times just before Jan 1, 1970. With a NULL pointer arg, time(2) can't fail. See the man page for details.)
On bare metal (in a custom OS), or in a DOS program:
%define RTCaddress 0x70
%define RTCdata 0x71
;Get time and date from RTC
.l1: mov al,10 ;Get RTC register A
out RTCaddress,al
in al,RTCdata
test al,0x80 ;Is update in progress?
jne .l1 ; yes, wait
mov al,0 ;Get seconds (00 to 59)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeSecond],al
mov al,0x02 ;Get minutes (00 to 59)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeMinute],al
mov al,0x04 ;Get hours (see notes)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeHour],al
mov al,0x07 ;Get day of month (01 to 31)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeDay],al
mov al,0x08 ;Get month (01 to 12)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeMonth],al
mov al,0x09 ;Get year (00 to 99)
out RTCaddress,al
in al,RTCdata
mov [RTCtimeYear],al
ret
This uses NASM, and is from here.
This will not work under a normal OS like Linux that stops user-space processes from directly accessing hardware. You could maybe get this to work as root, with an ioperm(2) system call to allow access to that I/O port. Linux only updates the BIOS/hardware RTC to match the current system time during shutdown, not continuously, so don't expect it to be perfectly in sync, especially if the motherboard battery is dead.
With NASM, if you are targeting Linux x86-64, you can simply do the following:
mov rax, 201
xor rdi, rdi
syscall
201 corresponds to the 64-bit system call number for sys_time (as listed here). Register rdi is set to 0 so the return value after performing the system call is stored in rax, but you could also make it point to a memory location of your choosing. The result is expressed in seconds since the Epoch.
More information about this system call can be found in the time man page.
As an addendum to the answer by Pyves above (using x86-64/NASM/Linux), if you want to get better clock resolution than a second, you can syscall with 228 instead of 201 to get seconds in one 64-bit variable and additional nanoseconds (beyond the seconds) in another 64-bit variable.
default rel
section .bss
time: resq 2 ; 2 qwords for seconds and nanoseconds
section .text
mov rax, 228 ; 228 is system call for sys_clock_gettime
xor edi, edi ; 0 for system clock (preferred over "mov rdi, 0")
lea rsi, [time]
syscall ; [time] contains number of seconds
; [time + 8] contains number of nanoseconds
From the man page, the system call is
int clock_gettime(clockid_t clock_id, struct timespec *tp);
struct timespec on x86-64 is a pair of unsigned 64-bit integers, with seconds at the low address, nanos at the higher address.
I'd say, depending on what platform you're on, you'll have to use an OS function.
On windows, try GetSystemTime. On linux, try gettimeofday - see related question here.
Related
I'm working on a ctf-like challenge and it is filtering my shellcode to make sure I don't have the hex value encodings of the syscall, sysenter and int instructions 0x0f05 0x0f34 and 0x80cd respectively. It has also disabled write permissions. I have a shellcode that can open a file which uses the sendfile system call but it includes the syscall instruction. The previous challenge was the same but with write permissions enabled. I successfully used a self-modifying shellcode in that challenge to get the flag.
This is the assembly code (with syscall) I used to read the file "flag" (GAS intel syntax):
.globl _start
_start:
.intel_syntax noprefix
mov rbx, 0x67616c66
push rbx
mov rax, 2
mov rdi, rsp
mov rsi, 0
syscall
mov rdi, 1
mov rsi, rax
mov rdx, 0
mov r10, 1000
mov rax, 40
syscall
mov rax, 60
syscall
I have been searching for an alternative way to do a system call in Linux for the past day but it seems impossible (I'm a newbie to assembly).
I read about an alternative way to do system calls by Call Gates method, but it seems to rely on the Global Descriptor Table and I don't think I can access that due to ASLR (Correct me if I'm wrong).
I'm not necessarily looking for an exact answer but just looking for some help understanding a way I can do a system call in this conditions.
I'm trying to increment 1 to a variable in IA32 Assembly in Linux
section .data
num: dd 0x1
section .text
global _start
_start:
add dword [num], 1
mov edx, 1
mov ecx, [num]
mov ebx,1
mov eax,4
int 0x80
mov eax,1
int 0x80
Not sure if it's possible to do.
In another literature I saw the follow code:
mov eax, num
inc eax
mov num, eax
Is it possible to increment a value to a var without moving to a register?
If so, do I have any advantage moving the value to a register?
Is it possible to increment a value to a var without moving to a register?
Certainly: inc dword [num].
Like practically all x86 instructions, inc can take either a register or memory operand. See the instruction description at http://felixcloutier.com/x86/inc; the form inc r/m32 indicates that you can give an operand which is either a 32-bit register or 32-bit memory operand (effective address).
If you're interested in micro-optimizations, it turns out that add dword [num], 1 may still be somewhat faster, though one byte larger, on certain CPUs. The specifics are pretty complicated and you can find a very extensive discussion at INC instruction vs ADD 1: Does it matter?. This is partly related to the slight difference in effect between the two, which is that add will set or clear the carry flag according to whether a carry occurs, while inc always leaves the carry flag unchanged.
If so, do I have any advantage moving the value to a register?
No. That would make your code larger and probably slower.
I'm trying to make a DOS program in NASM that uses interrupt 10h to display a pixel cycling through the 16 available colors in the top left corner. I also use interrupt 21h to only make the program run every 1/100 seconds (100 fps).
segment .data
pixelcolor: db 0
pixelx: dw 100
pixely: dw 100
timeaux: db 0 ; used later on to force the program to run at 100fps
segment .text
global _start
_start:
mov ah,00h
mov al,0dh
int 10h
mov ah,0bh
mov bh,00h
mov bl,00h
int 10h
.infinite:
mov ah,2ch
int 21h ; get system time
cmp dl,timeaux ; if 1/100 seconds haven't passed yet...
je .infinite ; ...skip current frame
; else, continue normally
mov byte[timeaux],dl
mov ah,00h
mov al,0dh
int 10h
mov ah,0bh
mov bh,00h
mov bl,00h
int 10h
mov ah,0ch
mov al,pixelcolor
mov cx,pixelx
mov dx,pixely
int 10h
inc byte[pixelcolor]
jmp .infinite
However, when I actually run the program in DOSBox, the pixel just stays red. Does anyone know why my infinite loops aren't working? (Note: I'm very new to NASM, so honestly I'm not even suprised my programs only work 15% of the time.)
The problem isn't actually the loop itself. What the loop is doing each iteration is the problem. Some issues and observations I have are:
Since this is a DOS COM program you will need an org 100h at the top since a COM program is loaded by the DOS loader to offset 100h of the current program segment. Without this the offsets of your data will be incorrect leading to data being read/written to from the wrong memory locations.
You have a problem with mov al,pixelcolor. It needs to be mov al,[pixelcolor]. Without square brackets1 the offset of pixelcolor is moved to AL, not what is stored at offset of pixelcolor. The same goes for pixelx and pixely. Your code prints the same pixel color (red in your case) to the wrong place2 on the screen repeatedly. This code:
mov ah,0ch
mov al,pixelcolor
mov cx,pixelx
mov dx,pixely
int 10h
inc byte[pixelcolor]
should be:
mov ah,0ch
mov al,[pixelcolor]
mov cx,[pixelx]
mov dx,[pixely]
int 10h
inc byte[pixelcolor]
It should be noted that the resolution of the timer by default will only be 18.2 times a second (~55ms). This is less resolution than the 1/100 of a second you are aiming for.
Some versions of DOS may always return 0 for the 1/100 of a second value.
Use of the BIOS to write pixels to the screen may make coding simpler (it abstracts away differences in the video modes) but will be quite slow compared to writing pixels directly to memory.
I would recommend Borland's Turbo Debugger (TD) for debugging DOS software. Turbo Debugger is included in a number of Borland's DOS C/C++ compiler suites.
Footnotes
1The use of brackets [] in NASM differs from MASM/TASM/JWASM.
2Although your question says you want to write to the upper left of the screen, the code suggests you really intended to write the pixel at coordinate 100,100.
Is it possible to make 64bit Linux loader to limit the address space of the loaded 32bit program to some upper limit?
Or to set some holes in the address space that to not be allocated by the kernel?
I mean for specific executable, not globally for all processes, neither through kernel configuration. Some code or ELF executable flags are examples of appropriate solution.
The limit should be forced for all loaded shared libraries as well.
Clarification:
The problem I want to fix is that my code uses the numbers above 0xc0000000 as a handle values and I want to clearly distinct between handle values and memory addresses, even when the memory addresses are allocated and returned by some third party library function.
As long as the address space in 64bit Linux is very close to 4G limit, there is no enough addressing space left for the handle values.
On the other hand 3GB or even less is far enough for all my needs.
OK, I found the answer of this question elsewhere.
The solution is to change the "personality" of your program to PER_LINUX32_3GB, using the Linux system call sys_personality.
But there is a problem. After switching to PER_LINUX32_3GB Linux kernel will not allocate space in the upper 1GB, but the already allocated space, for example the application stack, remains there.
The solution is to "restart" your program through sys_execve system call.
Here is the code where I packed everything in one:
proc ___SwitchLinuxTo3GB
begin
cmp esp, $c0000000
jb .finish ; the system is native 32bit
; check the current personality.
mov eax, sys_personality
mov ebx, -1
int $80
; and exit if it is what intended
test eax, ADDR_LIMIT_3GB
jnz .finish ; everything is OK.
; set the needed personality
mov eax, sys_personality
mov ebx, PER_LINUX32_3GB
int $80
; and restart the process
mov eax, [esp+4] ; argument count
mov ebx, [esp+8] ; the filename of the executable.
lea ecx, [esp+8] ; the arguments list.
lea edx, [ecx+4*eax+4] ; the environment list.
mov eax, sys_execve
int $80
; if something gone wrong, it comes here and stops!
int3
.finish:
return
endp
I am confused towards why/how a value gets printed in x86 assembly in a Linux environment.
For example if I wish to print a value I would do this:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx msgLength
int 80h
Now I understand the numerical value 4 will make the system call to sys_write after the interrupt. But my question is, what is the significance of the 4? Is it loading the address of the decimal value 4 into eax? Or is it loading the value 4 into the eax register?
I am confused after reading I can transfer the value at an address to a register using the following instruction:
mov eax, [msg]
eax will now contain the bytes at the address of msg, but I would guess this format is not acceptable:
mov eax, [4]
So what is really happening when I move 4 into eax to print something?
Simply the value (number) 4 is loaded into eax, no magic there. The operating system will look at the value in eax to figure out what function you want. System call number is a code that identifies the various available kernel functions you can use.
Linux kernel maintains all the system call routines as an array of function pointers (can be called as sys_call table) and the value in the eax gives the index to that array (which system call to choose) by the kernel. Other registers like ebx, ecx, edx contains the appropriate parameters for that system call routine.
And the int 80h is for software interrupt to the cpu from user mode to kernel mode because actual system call routine is kernel space function.