NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: jackjps on March 11, 2016, 04:54:29 PM
-
Very new to NASM so please don't assume I know what you are talking about.
I need to delay erasing a message on the screen so that the user can read it.
Is "times" what I need or just do a loop for 10,000 times or whatever?
Thanks for any help.
-
A loop will delay for different amounts of time on different machines. I think what you probably want is sys_nanosleep. I think sys_select can also be used for a delay. As usual, I might be able to dig up a 32-bit example, but not 64-bit.
Best,
Frank
-
Thanks Frank for responding.
I looked up on man sys_nanosleep/sys_select
2 sys_....
3
There was nothing there.
I have no idea how to code it.
A 32-bit example would be fine.
-
Very rudimentary. Just off the top of my head.
global _start
; nasm -f elf32 delay.asm
; ld -o delay delay.o -m elf_i386
section .data
msg db "read me quick!", 10
msg_len equ $ - msg
section .text
_start:
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
mov ecx, msg
mov edx, msg_len
int 80h
; put a time structure on the stack
push 0 ; nanoseconds
push 2 ; seconds
mov eax, 162 ; sys_nanosleep
mov ebx, esp ;point to our time structure (requested)
mov ecx, esp ; " (remaining)
int 80h
add esp, 8 ; "free" our time structure
mov eax, 1 ; sys_exit
mov ebx, 0 ; pretend no error
int 80h
Best,
Frank
-
I looked up on man sys_nanosleep/sys_select
2 sys_....
3
There was nothing there.
That does get kind of confusing, doesn't it. When assembly programmers say "sys_..." they mean the "System Call Function ..." Your manual pages list all system calls separate from other documentation, this means that if someone says "I think what you probably want is sys_nanosleep." The man page you should look up is man 2 nanosleep. All system calls are in man 2.
-
Thank you Bryant for responding.
Reason I couldn't find nanosleep on the man pages was I was keying
in sys_nanosleep.
I have read the man pages for nanosleep and as usual I don't
understand what I read.
Anyway I tried keying the following in my program:
call nanosleep 5
call sys_nanosleep 5
Got this error: comma, colon or end of line expected.
-
I'm sorry, this was my fault. I told you "look in section 2 of the man pages", but didn't explain that the man pages actually describe the C library functions, not the system calls underlying the C functions. They don't call anything "sys-anything". I'm pretty sure everything in section 2 is a system call. Other C library functions, which are not system calls, are in section 3 and other places.
I told you you didn't need to use C functions - which is true - but you're "supposed" to. The way you're "supposed" to do it - if you use assembly language at all - would be something like:
extern nanosleep
...
; for 32-bit code
push my_timestruc
push my_timestruc
; for 64-bit code?
mov rdi my_timestruc ; requested time
mov rsi my_timestruc ; remaining time
call nanosleep
really should continue with...
cmp eax/rax, -EINTER ; -4?
je do_it_again
I'm really not sure that's right. My original code has a comment ";does this work?". I don't know how to cause the sleep to be interrupted to test it. It "seems to work".
I'm not sure about the structure, either. The man page says:
time_t tv_seconds
long tv_nanoseconds
I've been using "dword" for both. Possible 64-bit code wants "qword"? If it's still "dword", you probably can't just push 'em on the stack as I did in my example.
The man pages also describe how the C functions handle errors. They typically return -1 and put the error number (a positive value) in ERRNO. The system calls actually return the negative of the error number in eax/rax. (pretty sure it's the same for 64-bit code?).
Best,
Frank
-
3-12-2015
Thanks for the help Frank.
As you can see this is what I got from me hopeless code.....
demo64.asm:111: error: parser: instruction expected
demo64.asm:113: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:113: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:113: error: (endstruc:1) `%$strucname_size': context stack is empty
demo64.asm:113: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:113: error: (endstruc:1) `%$strucname_size': context stack is empty
demo64.asm:113: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:113: error: label or instruction expected at start of line
demo64.asm:113: error: (endstruc:2) `%pop': context stack is empty
jack@jack-myheadache ~/nasmfld $
jstruct struc
time_t dq 5 ; 5 seconds
endstruc
mov rdi,time_t
mov rsi,time_t
call nanosleep
-
Well, that looks horrible... but isn't nearly as bad as it looks!
struc jstruc
... to begin with, then...
struc jstruc ; define, but do not allocate memory
time_t resq 5
endstruc
... but what I think we actually want is two members to the structure - seconds and nanoseconds. Possibly supposed to be qwords, but ASSuming still dwords in 64-bit...
struc jstruc
.seconds resd 1
.nsec resd 1
endstruc
I've used Nasm's "local label" mechanism (the dot) for the member names. I can re-use those names, but to refer to them outside this structure, I have to use "jstruc.seconds" and "jstruc.nsec". This is just a "typedef". Now we need to allocate memory for an instance of this thing:
section .data
thestruc istruc jstruc ; an instance of type jstruc
at jstruc.seconds dd 5
at jstruc.nsec dd 0
iend
...now...
; in section .text
mov rdi, thestruc
mov rsi, thestruc
; either
call nanosleep ; that's nanosleep(), the C lib function, declared extern somewhere
; or mov rax, sys_nanosleep (system call number)
; syscall ; the instruction
Simply putting "struc" in front and changing to "resb" (or q) eliminates a bunch of errors - poor Nasm was confused! :)
Best,
Frank
-
3-13-2016
Thanks Frank
This gave the following errors in 64-bit
during the compile:
demo64.asm:116: error: expecting `)'
demo64.asm:117: error: expecting `)'
demo64.asm:118: error: non-constant argument supplied to TIMES
I have no idea what your code does. If I read it in the man pages
I still probably won't understand it. Where can I read about it????
For instance: what is istruc, thestruc, resd??????
Do I have to declare "TIMES"????
;section data
extern nanosleep
116 thestruc istruc jstruc ; an instance of type jstruc
117 at jstruc.seconds dd 5
at jstruc.nsec dd 0
118 iend
struc jstruc
.seconds resd 1
.nsec resd 1
endstruc
;section text
mov rdi,thestruc
mov rsi,thestruc
call nanosleep
-
Something strange there. I have downloaded Nasm-2.12, but have not installed it. Let me do that and I'll get back to ya.
Best,
Frank
-
Typo in my code above! Needs a couple of commas:
section .data
thestruc istruc jstruc ; an instance of type jstruc
at jstruc.seconds, dd 5 ; needs comma
at jstruc.nsec, dd 0 ; here, too
iend
See if that'll help you any.
As you can see, all I know about structures is what I read in the manual. Trying to do it from memory isn't working out well. You aren't expected to use "times" - the "at" macro uses "times". It works, if we do everything right. If we flub it up, the error messages(s) typically aren't helpful, especially being a macro.
I wanted to install the same version of Nasm you're using, because there are a couple of bugs reported, one of which may have to do with "at". I don't think that's bothering you - it was my typo! (I think)
Update: you also have to use "struc", the typedef of the structure, before the "istruc", the instance of the structure - that gives a confusing error message about "times", too!
Best,
Frank
-
3-14-2016
Thanks Frank
This gave the following errors in 64-bit
during the compile:
jack@jack-myheadache ~/nasmfld $ nasm -f elf64 demo64.asm -o demo64
demo64.asm:115: error: expecting `)'
demo64.asm:116: error: expecting `)'
demo64.asm:117: error: non-constant argument supplied to TIMES
demo64.asm:117: error: parser: instruction expected
115 struc istruc jstruc ; an instance of type jstruc
116 at jstruc.seconds, dd 5 ; needs comma
117 at jstruc.nsec, dd 0 ; here, too
iend
;section data
extern nanosleep
struc istruc jstruc ; an instance of type jstruc
at jstruc.seconds, dd 5 ; needs comma
at jstruc.nsec, dd 0 ; here, too
iend
struc jstruc
.seconds resd 1
.nsec resd 1
endstruc
;section text
mov rdi,thestruc
mov rsi,thestruc
call nanosleep
-
I'm not doing a very good job of explaining this!
"struc" is a Nasm macro (it is defined in standard.mac, but you shouldn't have to delve into the Nasm source code). The fact that C (and perhaps other assemblers) spell it "struct" and Nasm spells it "struc" is a source of typos! I know "struc", but (perhaps unwisely) used ""jstruct" or sometimes "jstruc" as a name for the structure type. As a name for an instance of this type, I used "thestruc". This hasn't helped!
"struc" just defines the type of structure. It does not allocate any memory, or initialize anything. Often, we don't need to. For example, a structure that defines a directory entry can be filled with data from disk, without having an "istruc". In this case, we want an initialized instance of the structure. From "struc", Nasm defines the offsets to the members, and the size of the whole structure as "name_size". It uses the "times" mechanism to do this, which is why "times" often appears in the error message. (if it helps you, Masm uses "dup" instead of "times")
Perhaps it would be wise to use the same name for the type of structure that nanosleep expects as C uses: "timespec". I'll use the same names for the elements, too.
struc timespec
tv_sec resd 1
tv_nsec resd 1
endstruc
In this case I have not used Nasm's "local label" mechanism of starting the label with a dot. This means that you won't be able to use the names "tv_sec" and "tv_nsec" elsewhere in your program, but may simplify things otherwise. Nasm now knows that "tv_sec" is zero, "tv_nsec" is 4, and "timespec_size" is 8. Note that the member names are offsets from the start of the structure, not the complete address. We need to do this before creating an instance of this type.
Now we want an instance of this type of structure specifying 5 seconds (or whatever delay you want). Nasm uses the "istruc" macro for this. Suppose we call it "mytime".
mytime istruc timespec
at tv_sec, dd 5
at tv_nsec, dd 0
iend
We don't have to initialize all of the members. Nasm will initialize any we skip to zero (again using "times"). They do need to be "in order".
Actually, nanosleep expects two of these structures, or the second parameter can be NULL. I use the same structure for both "time requested" and "time remaining". I'm not sure this is correct, but it "seems to work". I would know if it didn't work only if nanosleep got interrupted, which probably doesn't happen very often (?).
This covers only the "delay", not actually deleting anything...
Best,
Frank
-
3-14-2016
Thanks Frank for your patience.
This gave the following errors in 64-bit
during the compile:
jack@jack-myheadache ~/nasmfld $ nasm -f elf64 demo64.asm -o demo64
demo64.asm:562: error: symbol `struc' undefined
demo64.asm:563: error: symbol `struc' undefined
;section data
extern nanosleep
struc timespec
tv_sec resd 1
tv_nsec resd 1
endstruc
mytime istruc timespec
at tv_sec, dd 5
at tv_nsec, dd 0
;section text
mov rdi,struc
mov rsi,struc
call nanosleep
-
;section text
mov rdi,struc
mov rsi,struc
call nanosleep
You want the name of the structure, "mytime", not the macro "struc" here.
Best,
Frank
-
3-14-2016
Thanks Frank,
This gave the following errors in 64-bit
during the compile:
demo64.asm:114: error: parser: instruction expected
demo64.asm:117: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:117: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:117: error: (endstruc:1) `%$strucname_size': context stack is empty
demo64.asm:117: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:117: error: (endstruc:1) `%$strucname_size': context stack is empty
demo64.asm:117: error: (endstruc:1) `%$strucname': context stack is empty
demo64.asm:117: error: label or instruction expected at start of line
demo64.asm:117: error: (endstruc:2) `%pop': context stack is empty
demo64.asm:119: error: symbol `mytime' redefined
demo64.asm:120: error: non-constant argument supplied to TIMES
demo64.asm:121: error: non-constant argument supplied to TIMES
;section data
extern nanosleep
114 mytime timespec
115 tv_sec resd 1
116 tv_nsec resd 1
117endstruc
119 mytime istruc timespec
120 at tv_sec, dd 5
121 at tv_nsec, dd 0
;section text
mov rdi,struc
mov rsi,struc
call nanosleep
-
May not actually work, but it assembles.
;section data
extern nanosleep
struc timespec
tv_sec resd 1
tv_nsec resd 1
endstruc
mytime istruc timespec
at tv_sec, dd 5
at tv_nsec, dd 0
iend
;section text
mov rdi,mytime
mov rsi,mytime
call nanosleep
Best,
Frank
-
Thanks for responding Frank,
I had to make this change to the struc to get it to work:
tv_sec resd 5
struc timespec
tv_sec resd 1?????
tv_nsec resd 1
endstruc
Since I don't know what I am doing, is this correct??
The process is to put an error message on the screen and let the user
have time to read it. Then I delete the message.
-
I don't know. My 32-bit man page says "time_t" for the seconds and "long" for nanoseconds. I tried to look up "time_t" and I still can't say I know...
http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to
I don't see any reason why we should reserve any more than 8 bytes, tops. Maybe you've got a really long error message, or a really slow-reading user. I'm an old geezer, and 2038 does not seem like a problem to me. :)
If one way works and the other doesn't, go with the way that works!
Best,
Frank