NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: jackjps on February 17, 2016, 11:35:57 AM

Title: beginner questions
Post by: jackjps on February 17, 2016, 11:35:57 AM
1st The captcha needs some work. Keeps on popping up after I have done it.
My 2nd post so please understand. Old windows programmer and absolutely green
with NASM.
Running Linux Mint 17.3 Rosa'

I started with NASM in the Linux Mint forum. That was a mistake.
Did not know about this forum.
From the Linux Mint forum I got the Linux System Call Table 64. Is this any good???
I got their test  Hello World program to work.
Moving on I have some questions:
1. how do I clear the screen
2. how do I put a colored rectangle on the screen
3.how do I put characters entered on the screen
4. how do I read the characters on the screen
5. Do I need any C functions. I don't do "C".
6. Does Printf write to the screen or the printer or both
7. where can I get a System call table 64-bit

I am trying to dump Windows.
Will have to rewrite hundreds of programs :'(
Would appreciate any help on getting started here.
Thanks for this site.
 



Title: Re: beginner questions
Post by: Frank Kotler on February 17, 2016, 11:32:43 PM
Hi jackjps,

Welcome to the Forum, and to Nasm, and to Linux. I hope that we'll be able to help you some - no guarantees!

To start with your last question, the system call list you got from the Mint forum "should" be okay. I thought we had one here:
http://forum.nasm.us/index.php?topic=1045.0
but that's just 32-bit. (has error numbers too)
There is definitely 32- and 64-bit system call numbers included in the NASMX macro package:
http://www.nasmx.sourceforge.net

Working backwards... "printf" writes to STDOUT - usually the screen, but it can be redirected to another file, including the printer.

No, you do not need C. That may sound strange, considering that both Nasm and Linux are written in C, but C doesn't have access to any instructions that are not available in assembly language. C has to access the kernel the same way we do - int 80h for 32-bit and the "syscall" instruction for 64-bit. It is quite convenient to just call code that someone else has written (and tested and maybe even optimized) but you don't "have" to (and don't let anyone tell you you do!)

I'll get back to your earlier questions, but as a quick hint - "VT100" (like ansi.sys in DOS, if you go back that far) and "in Unix, everything is a file".

Later,
Frank

Title: Re: beginner questions
Post by: Frank Kotler on February 18, 2016, 05:39:28 AM
This is not what I had  in mind! I came across it looking for something else. It is from Jeff Duntemann - looks like it's half-converted from DOS to Linux. The comments are still mostly DOS. I don't know where I got it. It shows some of the vt100 escape sequences. The remaining DOS parts (int 10h) will not work! The 32-bit Linux parts (int 80h) will need work to convert to 64-bit... but should work as 32-bit code. It may serve as a partial answer to how to do clearscreen. I'm going to post it while I've got my finger on it, although it is not working code. Apologies to Jeff for posting stuff he obviously wasn't finished with.
Code: [Select]
;  Source name     : VIDLIB.ASM
;  Compiled name   : VIDLIB.OBJ
;  Code model:     : Real mode segmented model
;  Version         : 1.0
;  Created date    : 9/12/1999
;  Last update     : 9/12/1999
;  Author          : Jeff Duntemann
;  Description     : A simple example of a separately assembled module
;                    containing utility procedures for controlling the
;                    PC display. Assembled using NASM 0.98.  DOS programs
;                    can link to these routines by declaring them EXTERN
;                    and then linking the program .OBJ to VIDLIB.OBJ using
;                    a linker like ALINK.



;----------------------------|
;     BEGIN DATA SEGMENT     |
;----------------------------|
           SEGMENT .data

;Note that the following items are defined externally to this module, and
;  for certain routines in this module to function these data items must
;  be linked in from a properly assembled external module.

           EXTERN  CRLF,LRXY

;----------------------------|
;     BEGIN CODE SEGMENT     |
;----------------------------|

           SEGMENT .text  ; This segment may be accessed externally

; Note that the following items are GLOBAL, and may be accessed by
;   external files that declare them EXTERN.

           GLOBAL GotoXY,ClrScr,ClrWin,ScrlWin,VIDEO6
           GLOBAL Write,Writeln


;---------------------------------------------------------------
;   GOTOXY    --  Positions the hardware cursor to X,Y
;   Last update 9/12/99
;
;   1 entry point:
;
;   GotoXY:
;      Caller must pass:
;      DL: X value     These are both 0-based; i.e., they
;      DH: Y value       assume a screen 24 by 79, not 25 by 80
;      Action:  Moves the hardware cursor to the X,Y position
;               loaded into DL and H.
;---------------------------------------------------------------
GotoXY:
    sub esp, 16
    mov edi, esp
    mov byte [edi], 27 ; "ESC"
    inc edi
    mov byte [edi], '['
    inc edi
    mov al, dh
    call al2dec
    mov byte [edi], ';'
    inc edi
    mov al, dl
    call al2dec
    mov byte [edi], 'H'
    inc edi
    mov byte [edi], 0
    mov edx, esp
    call Write
    add esp, 16
           ret               ; Return to the caller


al2dec:
    xor ecx, ecx
    mov bl, 10
.pushloop:
    mov ah, 0
    div bl
    push eax
    inc ecx
    cmp al, 0
    jnz .pushloop
.poploop:
    pop eax
    mov al, ah
    add al, '0'
    stosb
    loop .poploop
    ret

;---------------------------------------------------------------
;   CLRSCR    --  Clears or scrolls screens or windows
;   Last update 9/12/99
;
;   4 entry points:
;
;   ClrScr:
;      No values expected from caller
;      Action:  Clears the entire screen to blanks with 07H as
;               the display attribute
;
;   ClrWin:
;      Caller must pass:
;      CH: Y coordinate, upper left corner of window
;      CL: X coordinate, upper left corner of window
;      DH: Y coordinate, lower right corner of window
;      DL: X coordinate, lower right corner of window
;      Action:  Clears the window specified by the caller to
;               blanks with 07H as the display attribute
;
;   ScrlWin:
;      Caller must pass:
;      CH: Y coordinate, upper left corner of window
;      CL: X coordinate, upper left corner of window
;      DH: Y coordinate, lower right corner of window
;      DL: X coordinate, lower right corner of window
;      AL: number of lines to scroll window by (0 clears it)
;      Action:  Scrolls the window specified by the caller by
;               the number of lines passed in AL.  The blank
;               lines inserted at screen bottom are cleared
;               to blanks with 07H as the display attribute
;
;   VIDEO6:
;      Caller must pass:
;      CH: Y coordinate, upper left corner of window
;      CL: X coordinate, upper left corner of window
;      DH: Y coordinate, lower right corner of window
;      DL: X coordinate, lower right corner of window
;      AL: number of lines to scroll window by (0 clears it)
;      BH: display attribute for blanked lines (07H is "normal")
;      Action:  Generic access to BIOS VIDEO service 6.  Caller
;               must pass ALL register parameters as shown above
;---------------------------------------------------------------

ClrScr:
    sub esp, 16
    mov edi, esp
    mov byte [edi], 27
    inc edi
    mov byte [edi], '['
    inc edi
    mov byte [edi], '2'
    inc edi
    mov byte [edi], 'J'
    inc edi
    mov byte [edi], 0
    mov edx, esp
    call Write
    add esp, 16
    ret
   
           mov CX,0            ; Upper left corner of full screen
           mov DX,word [LRXY]  ; Load lower-right XY coordinates into DX
ClrWin:    mov AL,0            ; 0 specifies clear entire region
ScrlWin:   mov BH,07H          ; Specify "normal" attribute for blanked line(s)
VIDEO6:    mov AH,06H          ; Select VIDEO service 6: Initialize/Scroll
           int 10H             ; Call VIDEO
           ret                 ; Return to the caller


;---------------------------------------------------------------
;   WRITE    --  Displays information to the screen via DOS
;                service 9: Print String
;   Last update 9/12/99
;
;   1 entry point:
;
;   Write:
;      Caller must pass:
;      DS: The segment of the string to be displayed
;      DX: The offset of the string to be displayed
;          String must be terminated by "$"
;      Action:  Displays the string at DS:DX up to the "$" marker
;---------------------------------------------------------------

Write:
    mov ecx, edx
    or edx, byte -1
.getlen:
    inc edx
    cmp byte [ecx + edx], 0
    jnz .getlen
    mov ebx, 1
    mov eax, 4
    int 80h
    ret
   
;---------------------------------------------------------------
;   WRITELN  --  Displays information to the screen via DOS
;                service 9 and issues a newline
;   Last update 9/12/99
;
;   1 entry point:
;
;   Writeln:
;      Caller must pass:
;      DS: The segment of the string to be displayed
;      DX: The offset of the string to be displayed
;          String must be terminated by "$"
;      Action:  Displays the string at DS:DX up to the "$" marker
;               marker, then issues a newline.  Hardware cursor
;               will move to the left margin of the following
;               line.  If the display is to the bottom screen
;               line, the screen will scroll.
;      Calls: Write
;---------------------------------------------------------------

Writeln:
           call Write      ; Display the string proper through Write
           mov  eDX,CRLF    ; Load address of newline string to DS:DX
           call Write      ; Display the newline string through Write
           ret             ; Return to the caller

Later,
Frank

Title: Re: beginner questions
Post by: jackjps on February 18, 2016, 12:13:03 PM
Thank you Frank for a very informative response.

The Linux system call 64-bit list, I got from the Linux Mint forum, leaves a tad to be desired.
Some functions are obvious by the label and some are not obvious.
Where does one get an explanation of each call?


From what I see, NASM seems to replace windows API commands with
special functions (MACROS) like GOTOXY etc.
Fine. One wonders where there is a complete 64-bit list of these functions?
Will  go back and review NASMX again.
Title: Re: beginner questions
Post by: Frank Kotler on February 18, 2016, 03:14:19 PM
Hi jackjps,

I should make clear that I'm still running 32-bit and have very little experience with 64-bit. A long sad story. I'll cry on ya some other time.

Short answer - the system calls are in section 2 of the man pages. "man write" will give you the bash command, "man 2 write" will give you sys_write - or the "write()" wrapper for it. This is true for 32-bit, I'm pretty sure it's true of 64-bit. That may be the best that you can do. (it is in C terms, not asm terms)

NASMX has a lot of examples, but not much "documentation" as such. Rob Neff, who was maintaining NASMX, has just stepped down - "real life" interferes - so I don't know what's going to be happening with that...

Best,
Frank

Title: Re: beginner questions
Post by: jackjps on February 18, 2016, 09:47:53 PM
Thank you again Frank.
I hate to ask this question but I have to.
Where can I find the "man Pages"?
Title: Re: beginner questions
Post by: Frank Kotler on February 19, 2016, 12:17:33 AM
Ahhh... well.... hmmmm... I am embarrased to admit I don't know where the files are actually located. They're just "there". It's your "help system". /usr/man/ apparently. Linux differentiates between left and right alt and control keys - pressing left alt-control and some function key will get you into a console. (alt F7 will get you back into the GUI - you'll want to know that! :) )

Apparently, some distros don't have a "log in shell". You're just in the console, I guess. What I'm familiar with, and what I think you'll find, you have to log in (and give the password, of course). At that point, you can just type "man 2 write" (or some system call you don't know what it does) and get a description of what it does, what the parameters are, what it returns, and what the possible errors are. The man pages will claim that it returns -1 if error (usually) and the error number is in errno. If we call the system calls directly, the negative of the error number is in rax (eax for me). I ASSume there's a way to do all this from the GUI, but I don't know what it is. :)

Best,
Frank

Title: Re: beginner questions
Post by: jackjps on February 19, 2016, 11:51:07 AM
Hi Frank,
The instruction "man 2 write" works very well.
When in that hitting "h" gives a help screen with more info than
you want(mind boggling).

Here is a url to the Man Pages: http://kernel.org/doc/man-pages.
There is a ton of info there, that I have no idea how it applies to
assembler coding. As I don't do "C" why would I need this????

A suggestion if I may. You really need to be coding in 64-bit
as 32-bit is rapidly becoming obsolete.
Title: Re: beginner questions
Post by: Frank Kotler on February 19, 2016, 04:17:32 PM
What could I code in 64-bit that I can't code in 32-bit? In what sense is it "obsolete"?

Best,
Frank

Title: Re: beginner questions
Post by: jackjps on February 19, 2016, 08:02:14 PM
HI Frank,
I am assuming your have a 32-bit computer and running a 32-bit OS.
That's all fine and good. But you will find that running a 64-bit computer
with a 64-bit OS runs much faster, 64-bit architecture has been around
over 10 years and 32-bit is like running 16 bit when 32-bit is out.
Yes, you can run 32-bit programs on a 64-bit computer but it's not the
best way to do it IMHO.
Title: Re: beginner questions
Post by: Frank Kotler on February 20, 2016, 02:51:18 PM
You may be right.
Quote
But you will find that running a 64-bit computer
with a 64-bit OS runs much faster,
Do you have evidence of this, or is it an assumption? True of all programs, or just certain programs? What would make a good test case?
I am of the opinion that 64-bit code will run slower, other things being equal. It is, at this point, just my opinion.

Best,
Frank

Title: Re: beginner questions
Post by: Bryant Keller on February 20, 2016, 05:19:15 PM
jackjps,

On the thread that Frank linked you too earlier, I posted a "one-liner" command line that can be used to generate a header containing all the 64-bit system call numbers to their associated names. This command requires that you have glibc header collection installed from GCC.

Code: (Linux Console) [Select]
grep __NR $(locate unistd_64.h) | grep define | sed -e 's/\#/\%/' -e 's/__NR_/SYS_/' > unistd_64.inc
Note: the above one liner has changed slightly from the last version. Apparently GCC moved the header so we'll let the system find the file for us to make it more portable between versions.

The list that's generated should have each system call renamed using NASM's %define directive to it's symbolic counterpart. If you want to learn more about each specific system call, open that file and copy the name of the system call without the SYS_ part and use the man (or xman) utility to find information on that system call. An example session at your command prompt would look like this..

Code: [Select]
$ grep __NR $(locate unistd_64.h) | grep define | sed -e 's/\#/\%/' -e 's/__NR_/SYS_/' > unistd_64.inc
$ ls -a
.  ..  unistd_64.inc
$ head unistd_64.inc
%define SYS_read 0
%define SYS_write 1
%define SYS_open 2
%define SYS_close 3
%define SYS_stat 4
%define SYS_fstat 5
%define SYS_lstat 6
%define SYS_poll 7
%define SYS_lseek 8
%define SYS_mmap 9
$ man mmap

So, for someone new to Linux, a description of the above might be in order. The first command creates the file using a lot of "command line magic", you'll only have to do it once so don't get to focused on how it works right now (that's something fun for later). The second command (ls -a) lists all files and directories in your current working directory. In this case I was in a sub-directory that just had the unistd_64.inc that the first command created. The head command shows only the first few lines of a file. I used it as an example. If you want to scroll through the file, try using the less command instead of head. Next, I find a system call that I'm interested in. In this case I decided I wanted to know more about the SYS_mmap system call. As we can see, it is system call number 9... however, we don't know what parameters or what type of parameters it takes. This is where the man command comes in. Below is the output of the man mmap command executed below.

Code: (man mmap) [Select]
MMAP(2)                    Linux Programmer's Manual                   MMAP(2)

NAME
       mmap, munmap - map or unmap files or devices into memory

SYNOPSIS
       #include <sys/mman.h>

       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void *addr, size_t length);

       See NOTES for information on feature test macro requirements.

DESCRIPTION
       mmap()  creates a new mapping in the virtual address space of the call?
       ing process.  The starting address for the new mapping is specified  in
       addr.  The length argument specifies the length of the mapping.

       If addr is NULL, then the kernel chooses the address at which to create
       the mapping; this is the most portable method of creating  a  new  map?
       ping.   If  addr  is not NULL, then the kernel takes it as a hint about
       where to place the mapping; on Linux, the mapping will be created at  a
 Manual page mmap(2) line 1 (press h for help or q to quit)

In the manpages you can get an understanding of the parameters used by the routine, what error codes are returned and how they should be dealt with, and usually some program examples (written in C) showing how the system call is used.

Also note the name of the manual page is "mmap(2)". All system calls are in 2 and you can specify that on the command line. For example, if you were to use man stat you would notice that you get the output of the User Command stat(1) and this isn't what you want. To get to the system call, explicitly specify 2 on the command line with man 2 stat.

Earlier, I mentioned something called xman. This is a manual page viewer that comes with the X windows environment. This is a great tool to use when your exploring the various features of Linux. xman lets you browse through the documentation on your system using a graphical interface.
Title: Re: beginner questions
Post by: jackjps on February 21, 2016, 01:04:30 AM
To Frank,
It's my assumption. but it stand to reason that grabbing 4 bytes
has to be faster than grabbing 2 bytes. Don't take my word for it
but check it out on the internet.

To Bryant,
I'm working on understanding your post.
I'm afraid most of it is over my head, but
will give it a shot. Thank you.
 
Title: Re: beginner questions
Post by: Frank Kotler on February 21, 2016, 04:52:22 AM
Trying to convince me to not be such a luddite is probably not the best use of your time. We can discuss why "-f elfx32" exists as we go along. If you know a URL where I can download a clot of ambition... I have a 64-bit machine at my feet (my daughter's old machine)... I didn't say I had "no" experience with 64-bit code, only "very little". I installed "the wrong distro for me" on it. I shouldn't name the distro, since I have nothing nice to say about it, but... well... it was Mint. If it works for you, that's fine, but I need to resystem first thing. Not today... probably not tomorrow either...

Bryant just gave you the 64-bit syscall numbers and suggested "xman" to view the man pages from what I call the "cartoon interface". It isn't as complicated as it looks.

Best,
Frank

P.S. I agree about "captcha" but I don't know how to fix it. I think - I hope - that it'll go away and leave you alone soon.
Title: Re: beginner questions
Post by: jackjps on February 21, 2016, 03:22:52 PM
                  2-21-16
I hate to ask this basic stuff but I must.
Appreciate all your help.

 Questions about Linux and Nasm.
 1. don't know if I have 'glibc' or how to get it if I don't
    or what is does? What is GCC?
       I found glibc and installed it......
 2. what is VT100? I go back to the DOS days and card input
    and wiring boards. Glad that has come & gone.
 3. How do I program to use ex: 'gotoxy'?   
    I tried to use it and it failed because I don't know
    how to use it.
 4. What is the "BASH' command?
 5. What is 'xman'? Do I already have it? If so, where is it?
 6. do all commands (ex: write) use this sequence or are their
    variations:
    rax  for the system call
    rdi  for the output
    rsi  message length
    rdx  message length?
 7. in 'clrscr' What is Video6? Do I have it?
 8. if I do a man 2 pause, it says that I need to include
    '#include <unistd.h>'. When I add this to my program it fails

   
Title: Re: beginner questions
Post by: Frank Kotler on February 21, 2016, 06:29:50 PM
1) Well you've got "glibc". It's just a C library - there are different versions. "libc6"(?) is another "important" one. Although this is alleged to be "standardized", if you haven't got the right version, it won't work. "gcc" stands for "Gnu Compiler Collection", but is the name of the C compiler. Although you don't "need" to use it, you may want to. Even if you don't have any C code to compile, gcc knows what to tell ld, and may be easier than composing the command line to ld yourself. Incidentally, "ld" (the linker) and "objdump" and some other things are part of the "binutils" package and are not part of "gcc" although they go together.

2) If you remember DOS, you probably loaded "ansi.sys" in "config.sys" (or possibly "autoexec.bat").  It gave us the interface where up-arrow recalled previous commands, and the "escape sequences". Printing a string to the screen with the "escape" character (27 or 0x1B) followed by '[' and some numbers and letters would clear the screen, or change colors, or "gotoxy"... and some other things I forget. The vt100 interface does the same for us. We really should consult the "termcap" file (/etc/termcap) to make sure it's supported, but it probably is, and would just print some garbage if it isn't.

3) You mention "gotoxy" being a macro, which it could be. That stuff from Jeff Duntemann had it just as a subroutine. He composes an "escape sequence" on the stack and calls "write", which in this case expects a zero-terminated string. You'd want to replace it with a 64-bit "write", but would use the same escape sequence (I think) - on a 64-bit stack, of course.
Code: [Select]
mov dl, [x_pos]
mov dh, [y_pos]
call gotoxy
The x- and y- in dx is copied from the bios interrupt - you could do it a different way...

4) "bash" is the  "bourne again shell" - the most common(?) of the shells Unix uses. It serves the same purpose as "command.com" or "cmd.exe". You've got it.

5) "xman" is just the graphical interface to the man pages. You almost certainly have it. On my machine, it's at "/usr/X11R6/bin/xman". You could find it with "locate xman" or "which xman". I mentioned that there's probably a way to do this through the cartoon interface but I didn't know it. Bryant told us the way - "xman".

6) The system call number goes in rax, first parameter in rdi, second in rsi, third in rdx (different parameters for something other than sys_write, of course), r8 after that, I think. After that I'd have to look 'em up. In 32-bit code, system calls with a lot of parameters sometimes put 'em in a structure with just one parameter (ebx) pointed to 'em, rather than  edi, esi, ebp. Dunno if 64-bit does that.

7) I think "video6" is a remnant of the bios interrupt, not yet converted to Linux. You probably don't have it and shouldn't need it.

8 ) "unistd.h" is the C header file with the system call numbers. To include it in a Nasm file, you'd have to convert it to Nasm syntax (Bryant showed us a one-line script to do that) and probably name it "unistd.inc". NASMX has both 32- and 64-bit versions "%if"ed  based on the output format so we get the right one. I mentioned that the man pages are in C format rather than asm format - such is life.

Best,
Frank

Title: Re: beginner questions
Post by: jackjps on February 21, 2016, 09:53:12 PM
;OBJ   : Display a character
;------------------------------------------------
;RDI   : Address of the character
;       > add64, reg64
;------------------------------------------------
;NOTE   : -
;RETN   : -
;------------------------------------------------
prtchar:   
   push rax
   push    rdi
   mov   al,byte[rdi]
   call   prtchr
   pop    rdi
   pop    rax
   ret

Where did they get "prtchr"? It's not in the man pages.
Same with a "Pause".  Where did they get "getch"?
Title: Re: beginner questions
Post by: Frank Kotler on February 21, 2016, 10:52:55 PM
Dunno that one. Who is "they"?

"pause" is an instruction (introduced with P4 I think). "getch" is C (or possibly in "curses"?).

Best,
Frank

Title: Re: beginner questions
Post by: Bryant Keller on February 21, 2016, 11:20:21 PM
;OBJ   : Display a character
;------------------------------------------------
;RDI   : Address of the character
;       > add64, reg64
;------------------------------------------------
;NOTE   : -
;RETN   : -
;------------------------------------------------
prtchar:   
   push rax
   push    rdi
   mov   al,byte[rdi]
   call   prtchr
   pop    rdi
   pop    rax
   ret

Where did they get "prtchr"? It's not in the man pages.

It's defined within that file, it's just another procedure written by the author of that file. The man pages only document system calls and programs that are installed on the system. Using a text editor and searching for "prtchr:" takes me right to the following code:

Code: (nsm64.asm) [Select]
;--------------------------------
;#16 : prtchr(AL)
;OBJ : Display character in RAX
;--------------------------------
;ARG : The character in RAX(AL)
;--------------------------------
;NOTE : For internal use. Use prtchar
;RETN :
;--------------------------------
prtchr:
push rcx
push r11
push rdi
push rsi
push rdx
push rax
mov edx,1
mov rsi,rsp
mov edi,edx
mov eax,edx
syscall
pop rax
pop rdx
pop rsi
pop rdi
pop r11
pop rcx
ret

This is just a wrapper function that saves the registers and invokes the "write" system call (man 2 write). If you generate the file I mentioned earlier, you could look in there to see that SYS_write is defined as 1, in this example he puts 1 into EDX for the 'count' parameter to SYS_write and then reuses the value by copying it into EAX to specify the system call number to invoke with syscall instruction. Yeah, that's a lot to take in.. probably why it's listed as "For internal use".

Same with a "Pause".  Where did they get "getch"?

The getch procedure was defined on the line right after prtch:

Code: (nsm64.asm) [Select]
;------------------------------------------------
;#17 : getch(0)/AL
;OBJ : Get a character from keyboard
;------------------------------------------------
;ARG : -
;------------------------------------------------
;NOTE : Takes single character only
; : For internal use only. Use getchr.
;RETN : The key in AL
;------------------------------------------------
getch:
push rbp
mov rbp,rsp
sub rsp,16
push rdx
push rdi
push rsi
lea rsi,[rbp-2]
mov edx,1
xor edi,edi
xor eax,eax
syscall
xor eax,eax
mov al,byte[rbp-2]
pop rsi
pop rdi
pop rdx
mov rsp,rbp
pop rbp
ret

Once again, this is just a wrapper function that saves the registers and invokes the "read" system call (man 2 read). In this case, again referring to the unistd_64.inc file I told you to generate earlier, you can see that SYS_read is defined as 0. The author sets EAX to zero using the XOR instruction (because the exclusive OR of any value against itself is zero). This is a trick I'm guilty of using often myself, but makes the code less readable (which is why this code is also marked as "For internal use only.").

As Frank pointed out, the "they" here in your post wasn't exactly obvious. Took me a bit of searching to realize you were making a reference to an earlier post you had made on a different thread. Probably would have gotten an answer sooner if you had pointed out where you got the code you were using, that helps us help you.  ;D

Regards,
Bryant Keller
Title: Re: beginner questions
Post by: jackjps on February 22, 2016, 12:57:30 AM
I did get unistd_64.inc installed.
I see that I am going to have to watch what's in the rdx and
rdi registers. Yes, I didn't connect the 1st sample code to the 2nd
one. Didn't know that I had to do that. What does mov rsi,rsp do?

Seems this code is to ambiguous. I would think it could be written
in a straight forward manner. This kind of code is hard to decipher
6 months down the road. But what do I know.
Thank you for your response.
Title: Re: beginner questions
Post by: Frank Kotler on February 22, 2016, 02:37:31 AM
Thanks, Bryant! I didn't recognize that.
Quote
What does mov rsi,rsp do?
Since we're calling sys_write, rsi is the parameter that gives the address of the buffer that we're going to print. Since we pushed rax, and al holds the character we want to print, it tells sys_write that the character's on the stack. Since we started out with rdi pointed to the character,
Code: [Select]
mov rsi, rdi
might have been more straightforward, but might not have preserved all the registers we want to preserve. Or maybe it just seemed like a good idea at the time.

Quote
But what do I know.
Sounds like you know:
Quote
This kind of code is hard to decipher
6 months down the road.
On that, I think we are all agreed!

Best,
Frank

Title: Re: beginner questions
Post by: Bryant Keller on February 22, 2016, 04:24:09 AM
Thanks, Bryant! I didn't recognize that.

No problem.

Quote
This kind of code is hard to decipher
6 months down the road.
On that, I think we are all agreed!

Absolutely. I wouldn't suggest you try and learn from code like that. The code looks more like a wrapper to abstract the learner from the system, but what your wanting is to learn to code on a specific system. You need less abstractions, not more. :)

That said, I suggest you check out this awesome 64-bit NASM tutorial. I find myself recommending it a lot lately (and it's still not 100% complete). The coding style is clean, easy to read, and even the web page is quite well put together. What's more, he covers everything you've been trying to learn, check it out.

NASM Tutorial by Ray Toal (http://cs.lmu.edu/~ray/notes/nasmtutorial/)
Title: Re: beginner questions
Post by: jackjps on February 22, 2016, 11:43:59 AM
Thanks guys for putting up with me.
To Bryant,
I downloaded the NASM Tutorial by Ray Toal.
Lot in it . Will take me ages to absorb it.

In converting my 1st windows program these are some
of the things I need to do in NASM:
  create a full screen of a light blue color.
  put a small rectangle on the screen in yellow.
  let the user enter 4 digits in black in that rectangle.
  read the 4 digits from the rectangle.
Right now I can't get past the 1st item.

 


Title: Re: beginner questions
Post by: Bryant Keller on February 22, 2016, 07:53:56 PM
To Bryant,
I downloaded the NASM Tutorial by Ray Toal.
Lot in it . Will take me ages to absorb it.

Before you start any major projects on Linux, I would suggest reading that tutorial up to, and including, the section entitled "Understanding Calling Conventions". Once you understand how to interface with the system and make calls to the standard C library, you can then move forward to developing other stuff.

In converting my 1st windows program these are some
of the things I need to do in NASM:
  create a full screen of a light blue color.
  put a small rectangle on the screen in yellow.
  let the user enter 4 digits in black in that rectangle.
  read the 4 digits from the rectangle.
Right now I can't get past the 1st item.

I'll assume you want to do this in text mode, and that itself presents a few problems.

1st problem is that not all Linux systems are the same. What I mean by this is, Linux runs on a lot of different hardware and there are many different configurations and software options that the distribution mostly gets to customize themselves. The reason why this is a problem is because each terminal acts differently. Unlike DOS applications, when you open a console, you're actually connected through a Virtual Terminal (VT) to the system. These VTs emulate one of the popular terminals from the olden days of DEC's and HK's.. however, each of those terminals were built by different vendors and had different escape sequences for doing things beyond just text (like clearing the screen and changing text attributes). When people started building VTs for Linux, they did so around supporting the real terminals they liked and this has lead to a lot of options. Fortunately, however, this is mostly just an issue with history because almost every system I've ever used makes use of some form of DEC based VT (VT100, VT220, etc) but even those DEC ones (same vendor) aren't 100% the same. In fact, some don't even support color.

So how do we solve this problem? Well.. the same way you solve most problems with system dependency, through abstraction. If you put a portability layer between you and those terminals, you can develop code that should (in most cases) work on all those VTs. Luckily, you're not the first person to want this kind of abstraction. There is a C library called ncurses which provides a portable method of doing terminal graphics.
Title: Re: beginner questions
Post by: Bryant Keller on February 22, 2016, 08:00:36 PM
To demonstrate the use of ncurses, I took your program example and turned it into a basic use case then developed a demo app. Here's the source. Unfortunately, I run a 32-bit system so if you want to make this into a 64-bit demo.asm, you'll need to visit that tutorial and work your way through and convert this source. I stuck to libraries written in C so that you don't have to worry about calling conventions changing on you, both libc and libncurses are written in C.

Code: (demo.asm) [Select]
; Use Case:
;  - create a full screen of a light blue color.
;  - put a small rectangle on the screen in yellow.
;  - let the user enter 4 digits in black in that rectangle.
;  - read the 4 digits from the rectangle.

; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf demo.asm -o demo.o
;  gcc -o demo demo.o -lcurses


   bits 32
   cpu 586

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern atoi
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern keypad
   extern nonl
   extern cbreak
   extern echo
   extern has_colors
   extern start_color
   extern init_pair
   extern newwin
   extern endwin
   extern refresh
   extern wrefresh
   extern wgetnstr
   extern wbkgd

   extern LINES
   extern COLS

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h

   %define COLOR_BLACK     0
   %define COLOR_RED       1
   %define COLOR_GREEN     2
   %define COLOR_YELLOW    3
   %define COLOR_BLUE      4
   %define COLOR_MAGENTA   5
   %define COLOR_CYAN      6
   %define COLOR_WHITE     7
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

section .data

hWindow:       dd 0
hChildWindow:  dd 0
szUserInput:   db 0, 0, 0, 0, 0

section .text

;; do_init : nothing -> boolean .
;; preform all of the applications initialization.
;; when initialization was successful, hWindow will
;; contain the curses screen handle and the return
;; value will be TRUE. otherwise, it returns FALSE.
do_init:

   ;; setup an interrupt to terminate
   push dword do_exit
   push dword SIGINT
   call signal
   add esp, (2 * 4)

   ;; initialize the curses library
   call initscr

   ;; was curses initialization successful?
   cmp eax, 0
   jne .CursesInitSuccessful

   ;; initialization failed, return FALSE
   mov eax, FALSE
   ret

.CursesInitSuccessful:
   ;; save a copy of curses root window
   mov dword [hWindow], eax

   ;; enable keyboard mapping
   push dword TRUE
   push dword [hWindow]
   call keypad
   add esp, (2 * 4)

   ;; tell curses not to translate LF into CRLF on output
   call nonl

   ;; take input chars one at a time, no waiting for newline
   call cbreak

   ;; enable echoing of input
   call echo

   ;; does this system support color terminals?
   call has_colors
   cmp eax, 0
   jne .HasColorSupport

   ;; No color support, return FALSE
   mov eax, FALSE
   ret

.HasColorSupport:
   call start_color

   ;; create our color pairs

   ;; black foreground, blue background
   push dword COLOR_BLUE
   push dword COLOR_BLACK
   push dword BLACK_ON_BLUE
   call init_pair
   add esp, (3 * 4)

   ;; black foreground, yellow background
   push dword COLOR_YELLOW
   push dword COLOR_BLACK
   push dword BLACK_ON_YELLOW
   call init_pair
   add esp, (3 * 4)

   ;; lets create a child window

   push dword 50  ; x value
   push dword 10  ; y value
   push dword 5   ; 5 columns for 4 digits.
   push dword 1   ; 1 line for 1 row of digits.
   call newwin
   add esp, (4 * 4)
   mov [hChildWindow], eax

   ;; if we reach this point, we have initialized successfully.
   mov eax, TRUE
   ret

;; do_exit : integer -> nothing .
;; exit to the operating system.
do_exit:
   enter 0, 0

   ;; refresh our screen
   call refresh

   ;; shut down curses
   call endwin

   ;; return to operating system
   push dword 0
   call exit
   add esp, 4

   ;; we should never reach this point
   leave
   ret

;; clear_blue : nothing -> nothing .
;; create a full screen of a light blue color.
clear_blue:

   ;; make our background blue
   push dword COLOR_PAIR(BLACK_ON_BLUE)
   push dword [hWindow]
   call wbkgd
   add esp, (2 * 4)

   ;; refresh our screen
   push dword [hWindow]
   call wrefresh
   add esp, 4

   ret

;; draw_child_window : nothing -> nothing .
;; put a small rectangle on the screen in yellow.
draw_child_window:

   ;; make our background yellow
   push dword COLOR_PAIR(BLACK_ON_YELLOW)
   push dword [hChildWindow]
   call wbkgd
   add esp, (2 * 4)

   ;; refresh our child window
   push dword [hChildWindow]
   call wrefresh
   add esp, 4

   ret

;; get_user_input : nothing -> integer .
;; let the user enter 4 digits in black in that rectangle.
get_user_input:

   ;; get user input
   push dword 4 ; 4 characters
   push dword szUserInput
   push dword [hChildWindow]
   call wgetnstr
   add esp, (3 * 4)

   ;; convert string to integer
   push dword szUserInput
   call atoi
   add esp, 4
   ret

;; main : integer (string . string) -> integer .
;; our program starts here.
main:
   enter 0, 0

   call do_init
   cmp eax, TRUE
   jne .done

   ;; clear the screen to blue
   call clear_blue

   ;; draw yellow window
   call draw_child_window

   ;; get user input
   call get_user_input





   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;; At this point in our code, the number we ;;
   ;; entered into our child window is in the  ;;
   ;; EAX register. We can now use it for any- ;;
   ;; thing we want.                           ;;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




.done:
   push dword 0
   call do_exit
   leave
   ret
Title: Re: beginner questions
Post by: Frank Kotler on February 22, 2016, 08:04:02 PM
One of many...

http://www.termsys.demon.co.uk/vtansi.htm

Code: [Select]
global _start
; nasm -f elf32 bluescreen.asm
; ld -o bluescreen bluescreen.o -m elf_i386

section .data
bluescreen db 27, '[30;44m'
bluescreen_len equ $ - bluescreen

yellow db 27, '[30;43m'
yellow_len equ $ - yellow

cls db 27, '[2J'
cls_len equ $ - cls

msg db "hello vt100"
msg_len equ $ - msg


section .text
_start:
    mov eax, 4 ; sys_write
    mov ebx, 1 ; STDOUT
    mov ecx, bluescreen
    mov edx, bluescreen_len
    int 80h

    mov eax, 4 ; sys_write
    mov ebx, 1 ; STDOUT
    mov ecx, cls
    mov edx, cls_len
    int 80h

    mov eax, 4 ; sys_write
    mov ebx, 1 ; STDOUT
    mov ecx, yellow
    mov edx, yellow_len
    int 80h

    mov eax, 4 ; sys_write
    mov ebx, 1 ; STDOUT
    mov ecx, msg
    mov edx, msg_len
    int 80h


exit:
    mov ebx, 0
    mov eax, 1
    int 80h

This is extremely naive. It doesn't do exactly what you want, but may get you started. You will want to convert it to 64-bit, no doubt.

Best,
Frank

Title: Re: beginner questions
Post by: Frank Kotler on February 22, 2016, 08:40:24 PM
I forgot to mention one more Linux command: "reset". Learn to type it without seeing the letters and it may save your sanity if you're going to mess with the screen. :)

Bryant is right, of course. He's showing you how you "should" do it, I'm showing you how you "can" do it. If you're going to call C libraries, what's the assembly language for? Shouldn't you be programming in C? Assembly language is obsolete, isn't it? Just Joking!

(but seriously, they completely effed up the calling conventions in 64-bit - they are NOT the same!)

Best,
Frank

Title: Re: beginner questions
Post by: jackjps on February 22, 2016, 08:52:58 PM
Thanks again guys,
Oh my, I'm a glutton for punishment.
I think I have the glibc library. Not sure if I have the
ncurses library. I guess I have to look at the glibc
library through man. When I do man and an item
from the ncurses library nothing happens.
Will do my reading and conversion of Bryants program
until I heard about the ncurses library. Didn't think
I would have to get so involved with "C". But whatever
I have to do..... Windows 10 is an advertising mill by
a software company that has left the programming field! 
Title: Re: beginner questions
Post by: Bryant Keller on February 22, 2016, 09:19:05 PM
Bryant is right, of course. He's showing you how you "should" do it, I'm showing you how you "can" do it.

Well, I'm showing the way you can do it to get the most portability between terminals.. As for how you "should" do it... we'll, I can't exactly agree, I probably should have done better at documenting, it definitely needs refactoring  (though I was going for almost 1-1 translation to his use case), and I should probably check to make sure the string taken from my child window is actually a numeric value... but as far as a demo, it's fine. :P

If you're going to call C libraries, what's the assembly language for? Shouldn't you be programming in C? Assembly language is obsolete, isn't it? Just Joking!

I'm one of those weird people who actually find it easier to code in assembly than I do in high level languages. When I program in C I always feel like I'm fighting with the language to explain some concept that really shouldn't be so complicated. Assembler just gets out of my way and allows me to be productive.

To be honest, the languages I've always been most productive in have been Assembly, Scheme, and Forth.. though most work I've had to do professionally has been in C/C++, Fortran95, or Perl.

(but seriously, they completely effed up the calling conventions in 64-bit - they are NOT the same!)

Yeah, I still don't own a 64-bit machine, probably won't until Linux drops support for IA32...  :-[

Thanks again guys,
Oh my, I'm a glutton for punishment.
I think I have the glibc library. Not sure if I have the
ncurses library. I guess I have to look at the glibc
library through man. When I do man and an item
from the ncurses library nothing happens.

Check your distribution for ncurses-doc. that's the manual pages. For Debian, I installed ncurses using:

Code: (bash) [Select]
$ sudo apt-get install libncurses5-dev ncurses-doc
Will do my reading and conversion of Bryants program
until I heard about the ncurses library. Didn't think
I would have to get so involved with "C". But whatever
I have to do.....

You build code on top of other libraries all the time. Even the WinAPI was just an abstraction on top of the kernel mode API which is a library built on top of the BIOS which can be thought of as just yet another library. Since Linux is built on C and most of your applications are already running on top of the standard C library, there is very little reason not to use it.. It's there anyway. :P

Windows 10 is an advertising mill by
a software company that has left the programming field!

I've not used Windows since Win2k Professional...  ;D
Title: Re: beginner questions
Post by: jackjps on February 22, 2016, 09:36:22 PM
Thanks again Guys,
Got ncurses installed.
Changed the Demo  to 64 bit.
When I 1st ran the program it gave this error message:
no instruction for this cpulevel. Changed it to 686 and
got the same message.
Title: Re: beginner questions
Post by: Bryant Keller on February 22, 2016, 09:40:13 PM
the 686 was 32-bit also.. check out The NASM Manual - CPU Directive (http://www.nasm.us/doc/nasmdoc6.html#section-6.8). I think what you'll need is CPU IA64, though you could probably just remove that line.
Title: Re: beginner questions
Post by: jackjps on February 22, 2016, 09:55:03 PM
Got a clean compile.
I ran gcc -o demo64 demo64.o -lcurses
Have no idea what this is supposed to do.
Does it replace  ld -o demo64 demo54.o?
How do I run the program???????
Title: Re: beginner questions
Post by: Bryant Keller on February 22, 2016, 10:08:48 PM
I used gcc instead of ld because it's easier and I'm kinda lazy. The -o option specifies your output file. In the directory where you got a clean build, you should have a file named demo64 without any extension. that file should be marked executable. You can run it using the command ./demo64 in the same directory.
Title: Re: beginner questions
Post by: jackjps on February 22, 2016, 10:50:35 PM
nope. That gave me a segmentation fault.
Title: Re: beginner questions
Post by: Bryant Keller on February 22, 2016, 11:08:48 PM
Did you actually convert it to 64-bit code or just change the registers? The new calling convention is very different.
Title: Re: beginner questions
Post by: jackjps on February 23, 2016, 12:26:53 AM
Took out to save space.
Title: Re: beginner questions
Post by: Bryant Keller on February 23, 2016, 12:57:27 AM
You got to read the tutorial, the calling convention was changed to use registers and stack alignment is a big issue.

I have no way of testing this code, but this is a rough translation if you want to try and build it.

Code: (demo64.asm) [Select]
; Use Case:
;  - create a full screen of a light blue color.
;  - put a small rectangle on the screen in yellow.
;  - let the user enter 4 digits in black in that rectangle.
;  - read the 4 digits from the rectangle.

; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf64 demo64.asm -o demo64.o
;  gcc -o demo64 demo64.o -lcurses
;
; Run Process:
;   ./demo64


   bits 64

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern atoi
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern keypad
   extern nonl
   extern cbreak
   extern echo
   extern has_colors
   extern start_color
   extern init_pair
   extern newwin
   extern endwin
   extern refresh
   extern wrefresh
   extern wgetnstr
   extern wbkgd

   extern LINES
   extern COLS

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h

   %define COLOR_BLACK     0
   %define COLOR_RED       1
   %define COLOR_GREEN     2
   %define COLOR_YELLOW    3
   %define COLOR_BLUE      4
   %define COLOR_MAGENTA   5
   %define COLOR_CYAN      6
   %define COLOR_WHITE     7
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define STACK_ALIGN sub rsp, 8
   %define STACK_RESTORE add rsp, 8

section .data

hWindow:       dq 0
hChildWindow:  dq 0
szUserInput:   db 0, 0, 0, 0, 0

section .text

;; do_init : nothing -> boolean .
;; preform all of the applications initialization.
;; when initialization was successful, hWindow will
;; contain the curses screen handle and the return
;; value will be TRUE. otherwise, it returns FALSE.
do_init:
   STACK_ALIGN

   ;; setup an interrupt to terminate
   mov rsi, do_exit
   mov rdi, SIGINT
   call signal

   ;; initialize the curses library
   call initscr

   ;; was curses initialization successful?
   cmp rax, 0
   jne .CursesInitSuccessful

   ;; initialization failed, return FALSE
   STACK_RESTORE
   mov rax, FALSE
   ret

.CursesInitSuccessful:
   ;; save a copy of curses root window
   mov [hWindow], rax

   ;; enable keyboard mapping
   mov rsi, TRUE
   mov rdi, [hWindow]
   call keypad

   ;; tell curses not to translate LF into CRLF on output
   call nonl

   ;; take input chars one at a time, no waiting for newline
   call cbreak

   ;; enable echoing of input
   call echo

   ;; does this system support color terminals?
   call has_colors
   cmp rax, 0
   jne .HasColorSupport

   ;; No color support, return FALSE
   STACK_RESTORE
   mov rax, FALSE
   ret

.HasColorSupport:
   call start_color

   ;; create our color pairs

   ;; black foreground, blue background
   mov rdx, COLOR_BLUE
   mov rsi, COLOR_BLACK
   mov rdi, BLACK_ON_BLUE
   call init_pair

   ;; black foreground, yellow background
   mov rdx, COLOR_YELLOW
   mov rsi, COLOR_BLACK
   mov rdi, BLACK_ON_YELLOW
   call init_pair

   ;; lets create a child window
   mov rcx, 50    ; x value
   mov rdx, 10    ; y value
   mov rsi, 5     ; 5 columns for 4 digits
   mov rdi, 1     ; 1 line for 1 row of digits
   call newwin
   mov [hChildWindow], rax

   ;; if we reach this point, we have initialized successfully.
   STACK_RESTORE
   mov rax, TRUE
   ret

;; do_exit : integer -> nothing .
;; exit to the operating system.
do_exit:
   STACK_ALIGN

   ;; refresh our screen
   call refresh

   ;; shut down curses
   call endwin

   ;; return to operating system
   mov rdi, 0
   call exit

   ;; we should never reach this point
   STACK_RESTORE
   ret

;; clear_blue : nothing -> nothing .
;; create a full screen of a light blue color.
clear_blue:
   STACK_ALIGN

   ;; make our background blue
   mov rsi, COLOR_PAIR(BLACK_ON_BLUE)
   mov rdi, [hWindow]
   call wbkgd

   ;; refresh our screen
   mov rdi, [hWindow]
   call wrefresh

   STACK_RESTORE
   ret

;; draw_child_window : nothing -> nothing .
;; put a small rectangle on the screen in yellow.
draw_child_window:
   STACK_ALIGN

   ;; make our background yellow
   mov rsi, COLOR_PAIR(BLACK_ON_YELLOW)
   mov rdi, [hChildWindow]
   call wbkgd

   ;; refresh our child window
   mov rdi, [hChildWindow]
   call wrefresh

   STACK_RESTORE
   ret

;; get_user_input : nothing -> integer .
;; let the user enter 4 digits in black in that rectangle.
get_user_input:
   STACK_ALIGN

   ;; get user input
   mov rdx, 4
   mov rsi, szUserInput
   mov rdi, [hChildWindow]
   call wgetnstr

   ;; convert string to integer
   ;; rdi, rsi, rdx, rcx, r8, r9
   mov rdi, szUserInput
   call atoi

   STACK_RESTORE
   ret

;; main : integer (string . string) -> integer .
;; our program starts here.
main:
   STACK_ALIGN

   call do_init
   cmp rax, TRUE
   jne .done

   ;; clear the screen to blue
   call clear_blue

   ;; draw yellow window
   call draw_child_window

   ;; get user input
   call get_user_input





   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;; At this point in our code, the number we ;;
   ;; entered into our child window is in the  ;;
   ;; RAX register. We can now use it for any- ;;
   ;; thing we want.                           ;;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




.done:
   STACK_RESTORE
   xor rdi, rdi
   call do_exit
   ret

Let me know if it works... technically this will have been my first IA64 application. ;D
Title: Re: beginner questions
Post by: jackjps on February 23, 2016, 12:21:47 PM
Getting compile errors with this.
undefined reference to all the "C" functions
In 64-bit shouldn't all the calls be changed to "syscall"???

Generally I try to avoid the stack like the plague.
Only use it for pushes and pop.
I think I see how you avoid the stack hassle by using
stack align and stack restore.
Why can't I use the registers instead of the stack????

Could I possibly have "glibc" in the wrong place?
I put the demo64 program in home/jack/nasmfld
This is what I get when running gcc -o demo64 demo64.o -lcurses nasmbld:
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 21
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o:/build/eglibc-3GlaMS/eglibc-2.19/csu/../sysdeps/x86_64/start.S:118: first defined here
collect2: error: ld returned 1 exit status

Got these errors using:  ld -o demo64 demo64.o in home/jack/nasmfld:
jack@jack-myheadache ~/nasmfld $ ld -o demo64 demo64.o:
demo64.o: In function `do_init':
demo64.asm:(.text+0x14): undefined reference to `signal'
demo64.asm:(.text+0x19): undefined reference to `initscr'
demo64.o: In function `do_init.CursesInitSuccessful':
demo64.asm:(.text+0x3f): undefined reference to `keypad'
demo64.asm:(.text+0x44): undefined reference to `nonl'
demo64.asm:(.text+0x49): undefined reference to `cbreak'
demo64.asm:(.text+0x4e): undefined reference to `echo'
demo64.asm:(.text+0x53): undefined reference to `has_colors'
demo64.o: In function `do_init.HasColorSupport':
demo64.asm:(.text+0x68): undefined reference to `start_color'
demo64.asm:(.text+0x7c): undefined reference to `init_pair'
demo64.asm:(.text+0x90): undefined reference to `init_pair'
demo64.asm:(.text+0xa9): undefined reference to `newwin'
demo64.o: In function `do_exit':
demo64.asm:(.text+0xc4): undefined reference to `refresh'
demo64.asm:(.text+0xc9): undefined reference to `endwin'
demo64.asm:(.text+0xd0): undefined reference to `exit'
demo64.o: In function `clear_blue':
demo64.asm:(.text+0xef): undefined reference to `wbkgd'
demo64.asm:(.text+0xfc): undefined reference to `wrefresh'
demo64.o: In function `draw_child_window':
demo64.asm:(.text+0x117): undefined reference to `wbkgd'
demo64.asm:(.text+0x124): undefined reference to `wrefresh'
demo64.o: In function `get_user_input':
demo64.asm:(.text+0x149): undefined reference to `wgetnstr'
jack@jack-myheadache ~/nasmfld $


;------------------------------------------------
;   2-23-2016 using NASM 64
;   Order of colors: BGR
;
; Bryants goodies
; Use Case:
;  - create a full screen of a light blue color.
;  - put a small rectangle on the screen in yellow.
;  - let the user enter 4 digits in black in that rectangle.
;  - read the 4 digits from the rectangle.

; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf64 demo64.asm -o demo64.o
;  gcc -o demo64 demo64.o -lcurses

; Run Process:
;   ./demo64

   bits 64
   cpu IA64

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern atoi
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern keypad
   extern nonl
   extern cbreak
   extern echo
   extern has_colors
   extern start_color
   extern init_pair
   extern newwin
   extern endwin
   extern refresh
   extern wrefresh
   extern wgetnstr
   extern wbkgd

   extern LINES
   extern COLS

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h

   %define COLOR_BLACK     0
   %define COLOR_RED       1
   %define COLOR_GREEN     2
   %define COLOR_YELLOW    3
   %define COLOR_BLUE      4
   %define COLOR_MAGENTA   5
   %define COLOR_CYAN      6
   %define COLOR_WHITE     7
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define STACK_ALIGN sub rsp, 8
   %define STACK_RESTORE add rsp, 8

section .data

hWindow:       dq 0
hChildWindow:  dq 0
szUserInput:   db 0, 0, 0, 0, 0

section .text
    global _start    ;??
_start:              ;??

;; do_init : nothing -> boolean .
;; preform all of the applications initialization.
;; when initialization was successful, hWindow will
;; contain the curses screen handle and the return
;; value will be TRUE. otherwise, it returns FALSE.
do_init:
   STACK_ALIGN

   ;; setup an interrupt to terminate
   mov rsi,do_exit
   mov rdi,SIGINT
   call signal

   ;; initialize the curses library
   call initscr

   ;; was curses initialization successful?
   cmp rax,0
   jne .CursesInitSuccessful

   ;; initialization failed, return FALSE
   mov rax,FALSE
   ret

.CursesInitSuccessful:
   ;; save a copy of curses root window
   mov [hWindow],rax

   ;; enable keyboard mapping
   mov rsi,TRUE
   mov rdi,[hWindow]
   call keypad

   ;; tell curses not to translate LF into CRLF on output
   call nonl

   ;; take input chars one at a time, no waiting for newline
   call cbreak

   ;; enable echoing of input
   call echo

   ;; does this system support color terminals?
   call has_colors
   cmp rax,0
   jne .HasColorSupport

   ;; No color support, return FALSE
   STACK_RESTORE
   mov rax,FALSE
   ret

.HasColorSupport:
   call start_color

   ;; create our color pairs

   ;; black foreground, blue background
   mov rdx, COLOR_BLUE
   mov rsi, COLOR_BLACK
   mov rdi, BLACK_ON_BLUE
   call init_pair

   ;; black foreground, yellow background
   mov rdx, COLOR_YELLOW
   mov rsi, COLOR_BLACK
   mov rdi, BLACK_ON_YELLOW
   call init_pair

   ;; lets create a child window

   mov rcx, 50    ; x value
   mov rdx, 10    ; y value
   mov rsi, 5     ; 5 columns for 4 digits
   mov rdi, 1     ; 1 line for 1 row of digits
   call newwin
   mov [hChildWindow],rax

   ;; if we reach this point, we have initialized successfully.
   STACK_RESTORE
   mov rax,TRUE
   ret

;; do_exit : integer -> nothing .
;; exit to the operating system.
do_exit:
   STACK_ALIGN

   ;; refresh our screen
   call refresh

   ;; shut down curses
   call endwin

   ;; return to operating system
   push qword 0
   call exit
   add rsp,4

   ;; we should never reach this point
   STACK_RESTORE
   ret

;; clear_blue : nothing -> nothing .
;; create a full screen of a light blue color.
clear_blue:
   STACK_ALIGN

   ;; make our background blue
   mov rsi,COLOR_PAIR(BLACK_ON_BLUE)
   mov rdi,[hWindow]
   call wbkgd

   ;; refresh our screen
   mov rdi, [hWindow]
   call wrefresh
   STACK_RESTORE
   ret

;; draw_child_window : nothing -> nothing .
;; put a small rectangle on the screen in yellow.
draw_child_window:
   STACK_ALIGN

   ;; make our background yellow
   mov rsi, COLOR_PAIR(BLACK_ON_YELLOW)
   mov rdi, [hChildWindow]
   call wbkgd

   ;; refresh our child window
   mov rdi,[hChildWindow]
   call wrefresh
   STACK_RESTORE
   ret

;; get_user_input : nothing -> integer .
;; let the user enter 4 digits in black in that rectangle.
get_user_input:
   STACK_ALIGN

   ;; get user input
   mov rdx, 4
   mov rsi, szUserInput
   mov rdi, [hChildWindow]
   call wgetnstr

   ;; convert string to integer
   ;; rdi, rsi, rdx, rcx, r8, r9
   mov rdi,szUserInput
   call atoi
   STACK_RESTORE
   ret

;; main : integer (string . string) -> integer .
;; our program starts here.
main:
   STACK_ALIGN

   call do_init
   cmp rax,TRUE
   jne .done

   ;; clear the screen to blue
   call clear_blue

   ;; draw yellow window
   call draw_child_window

   ;; get user input
   call get_user_input

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;; At this point in our code, the number we ;;
   ;; entered into our child window is in the  ;;
   ;; RAX register. We can now use it for any- ;;
   ;; thing we want.                           ;;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.done:
   STACK_RESTORE
   xor rdi, rdi
   call do_exit
   ret



 
Title: Re: beginner questions
Post by: Bryant Keller on February 24, 2016, 12:31:05 AM
In 64-bit shouldn't all the calls be changed to "syscall"???

The syscall instruction invokes an operating system routine, sorta like how on 32-bit systems you do so with the int instruction. What we are doing is invoking procedures that are present in a shared library, so we need to use call instead. Just like in Win32, when you want to use CreateFile or some other procedure, you use the call instruction instead of int 0x2E operating system service directly.

Generally I try to avoid the stack like the plague.
Only use it for pushes and pop.
I think I see how you avoid the stack hassle by using
stack align and stack restore.
Why can't I use the registers instead of the stack????

Actually, I am using registers. This is some of that weirdness that they did to the calling convention that Frank and I was talking about. The new convention is to put values in registers so you can call procedures faster. However, the stack pointer must be aligned on a 16-byte value before you make a call. That sounds fine, except that call pushes the return address onto the stack (an 8-byte value) so if you're aligned before a call, your unaligned in the routine. What I do here is, at the start of each subroutine I realign the stack back to a 16-byte boundary and before each ret I restore stack pointer so that the return address is back in place. This craziness is a total waste of memory but is something that Intel thought was a good idea. This isn't a Linux thing, Windows has to do the same thing (except they also require shadow space which is like backup stack space for registers....)

Could I possibly have "glibc" in the wrong place?
I put the demo64 program in home/jack/nasmfld
This is what I get when running gcc -o demo64 demo64.o -lcurses nasmbld:
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 13
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 21
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o:/build/eglibc-3GlaMS/eglibc-2.19/csu/../sysdeps/x86_64/start.S:118: first defined here
collect2: error: ld returned 1 exit status

I've actually never seen this error before, it might be worth it to find someone more experienced with 64-bit development to explain that. Those errors are referring to something in the C runtime, but aside from that.... I dunno what to make of it.

EDIT:
I just noticed you modified the code I posted. You don't need global _start and _start: in your code. The _start label is used internally, because you're making use of the C library, there are some initialization routines that need to be setup for you. In the original example, our entry point is at main which is a function called by the standard C library after that initialization. Remove those two lines and try again. I think that's what is causing it.

Got these errors using:  ld -o demo64 demo64.o in home/jack/nasmfld:
jack@jack-myheadache ~/nasmfld $ ld -o demo64 demo64.o:
demo64.o: In function `do_init':
demo64.asm:(.text+0x14): undefined reference to `signal'
demo64.asm:(.text+0x19): undefined reference to `initscr'
demo64.o: In function `do_init.CursesInitSuccessful':
demo64.asm:(.text+0x3f): undefined reference to `keypad'
demo64.asm:(.text+0x44): undefined reference to `nonl'
demo64.asm:(.text+0x49): undefined reference to `cbreak'
demo64.asm:(.text+0x4e): undefined reference to `echo'
demo64.asm:(.text+0x53): undefined reference to `has_colors'
demo64.o: In function `do_init.HasColorSupport':
demo64.asm:(.text+0x68): undefined reference to `start_color'
demo64.asm:(.text+0x7c): undefined reference to `init_pair'
demo64.asm:(.text+0x90): undefined reference to `init_pair'
demo64.asm:(.text+0xa9): undefined reference to `newwin'
demo64.o: In function `do_exit':
demo64.asm:(.text+0xc4): undefined reference to `refresh'
demo64.asm:(.text+0xc9): undefined reference to `endwin'
demo64.asm:(.text+0xd0): undefined reference to `exit'
demo64.o: In function `clear_blue':
demo64.asm:(.text+0xef): undefined reference to `wbkgd'
demo64.asm:(.text+0xfc): undefined reference to `wrefresh'
demo64.o: In function `draw_child_window':
demo64.asm:(.text+0x117): undefined reference to `wbkgd'
demo64.asm:(.text+0x124): undefined reference to `wrefresh'
demo64.o: In function `get_user_input':
demo64.asm:(.text+0x149): undefined reference to `wgetnstr'
jack@jack-myheadache ~/nasmfld $

Now these errors I'm familiar with. The problem here is that ncurses isn't being linked in and so ld can't find those functions. In fact, given the command line you posted, I'm surprised you're not getting more errors. The reason people tend to use GCC instead of LD directly is because GCC will search for and find the startup routines and libraries you need. On my 32-bit Linux system, I can link the original 32-bit demo.o with the command:

Code: [Select]
ld -s -o demo /usr/lib/i386-linux-gnu/crti.o /usr/lib/i386-linux-gnu/crt1.o /usr/lib/i386-linux-gnu/crtn.o -I/lib/ld-linux.so.2 demo.o -lc -lcurses
This is considerably longer than the alternative GCC form of:

Code: [Select]
gcc -o demo demo.o -lcurses
As you can see, I'm referencing crti.o, crt1.o, crtn.o and ld-linux.so.2... however, these aren't always installed in the same place on your system. That's why GCC is so useful, it'll find those files for you. I recommend using it instead of LD directly.

Title: Re: beginner questions
Post by: jackjps on February 24, 2016, 02:44:42 AM
Thanks Bryant,
I took out global_start and _start.
Everything worked :)
Got a light blue screen and a light yellow rectangle.
It accepted  4 digits.

Hope it's ok for me to delete my long post like I did the other one.
I'll evidently have more questions as I proceed with the program.
I really don't understand all the things you did or if I should spend
a lot of time trying to figure it out or proceed with the program
and hope with more learning of NASM that things will eventually
fall in place.

The blue screen takes up about 1/4 of the screen and should be
the entire screen. Would like a lighter blue. The yellow rectangle
needs to be a brighter yellow. How to place the rectangle in a
different place on the screen?  Want to place a message for
the user in front of the rectangle on the same line.

I am hoping your example will give me enough NASM knowledge
to do the other 199 programs I need to convert.

Another problem I need to worry about. With all these added programs,
and the "C" lib and tutorials, I would never be able to reconstruct
what I have now, if I lost it all due to a meteorite hitting my computer.
Of course I do back up the computer regularly. Maybe I am to paranoid.
 
One wonders how others trying to write or convert programs in
NASM manage. I certainly couldn't....



Title: Re: beginner questions
Post by: Bryant Keller on February 24, 2016, 06:08:49 AM
Thanks Bryant,
I took out global_start and _start.
Everything worked :)

Congrats to both of us then. You got it working and I've done my first working 64-bit program.  ;)

Got a light blue screen and a light yellow rectangle.
It accepted  4 digits.

Yep, that's pretty much the use case you mentioned. I hope it's enough of a starting point from you to learn more from. If you have any other questions, don't hesitate to ask. We are always glad to help.

Hope it's ok for me to delete my long post like I did the other one.
I'll evidently have more questions as I proceed with the program.
I really don't understand all the things you did or if I should spend
a lot of time trying to figure it out or proceed with the program
and hope with more learning of NASM that things will eventually
fall in place.

I don't think you can delete your old post after it's been replied too after a certain amount of time. Leave it, it'll be useful for others who follow in your footsteps to see the progression of the conversation.

The blue screen takes up about 1/4 of the screen and should be
the entire screen.

Not sure why it's doing that, the 32-bit one fills the entire screen on mine. I've tested in both xfce4-terminal and xterm. The only issues I've had has been that xfce4-terminal messes up the colors a little, but that can be adjusted with modifying the preferences.

Would like a lighter blue. The yellow rectangle
needs to be a brighter yellow.

There are various text attributes you can change (underline, bold, blink, etc) but my knowledge and use of curses is fairly limited. Most of that information can be gleamed from looking through the C header curses.h but (as with most portability projects) there are a lot of macros involved in making the system portable and it can be difficult to wade through sometimes. A lot of times to save myself the trouble of hunting through macros to find out a value, I'll just write a simple C program that includes the header and uses printf to display the resulting number, for example if I read the manual pages and find out that you can set a bold attribute of a window by giving the wattron option the A_BOLD value, I can find out what value I should set A_BOLD to by writing up this quick C program:

Code: (bold.c) [Select]
#include <stdio.h>
#include <curses.h>

int main (void)
{
  printf ("%%define A_BOLD 0x%X\n", A_BOLD);
  return (0);
}[/bold]

Building and running this program gives me the following output:

[code]$ gcc -o bold bold.c
$ ./bold
%define A_BOLD 0x200000
$

This is the exact line we would put into our NASM source (or possibly a header to be included in our source) to allow us to use A_BOLD.

How to place the rectangle in a different place on the screen?  Want to place a message for
the user in front of the rectangle on the same line.

To create the rectangle I get the users text from, i created a child window. During that windows creation, I set it's coordinates on the screen. I put comments explaining what each of the arguments were for that, search the source for line containing call newwin, above that I setup the parameters and put comments in place describing what the values mean. You should compare that to the man page for newwin.

The ncurses library provides you with a function for moving the windows cursor called wmove and a function for writing text on the screen called waddnstr. You could easily do what you want with those.

Just to get you ahead of the game, what you're actually describing would be accomplished using the ncurses forms library. Right now, I would suggest just getting good at the basics of 64-bit Linux Assembly then worry about doing more advanced interfaces. However, if you decide to really get into this ncurses stuff. The following tutorial will help you tremendously.

NCURSES Programming HOWTO (http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/)

The NCURSES Forms library allows you to create the label and field style input you're leading up to.

I am hoping your example will give me enough NASM knowledge
to do the other 199 programs I need to convert.

Sounds like quite the code base to work on. Lots of opportunity for refining your skills in the Linux environment. :)

Another problem I need to worry about. With all these added programs,
and the "C" lib and tutorials, I would never be able to reconstruct
what I have now, if I lost it all due to a meteorite hitting my computer.
Of course I do back up the computer regularly. Maybe I am to paranoid.
 
One wonders how others trying to write or convert programs in
NASM manage. I certainly couldn't....

Well, i don't have meteorite insurance, but I keep most of my backups on USB disk or SD cards. I've got quite a few of both in my desk drawer. If you're looking for public code management, you can always use SVN or GIT and a hosted repository like SourceForge (http://sourceforge.net) or GitHub (http://www.github.com). The NASM project itself is hosted on a GIT repository called repo.or.cz (http://repo.or.cz). Managing your project with these tools are a good idea, though a bit complicated to use if you're not used to version control systems (VCS). I'm only just now getting used to using them, sad since a few projects I've been involved with have used both.  :-[
Title: Re: beginner questions
Post by: jackjps on February 24, 2016, 11:31:44 AM
Thanks again Bryant,
It will take a bunch of time to wade through your last post
and read the ncurses howto.

OK, I won't delete my last long post.
In order to save space on the NASM site, if I have to post
a lot of code again, how do you do that scrolling goodie
you use?
Title: Re: beginner questions
Post by: Bryant Keller on February 24, 2016, 12:43:30 PM
In order to save space on the NASM site, if I have to post
a lot of code again, how do you do that scrolling goodie
you use?

That "scrolling goodie" is called a code block. There are two ways to do it. When your editing a post, there are a number of formatting buttons above the text area that you type in. Once you've entered your code into the text area, highlight the text by selecting it, then click the button marked with a # character. This will wrap the code you entered in the proper code tags. The second way is to enter them manually, for example:

[CODE]This is source code[/CODE]

Will create the following:

Code: [Select]
This is source code
If your code is really long, the code block will add a scrollbar to save on visible space. What's even more important is that the code block formats your code in a fixed with font, this means that code is easier to read. To be honest, of all the formatting features available on these forums, the code blocks are by far the most useful and should be used as much as possible. ;D
Title: Re: beginner questions
Post by: jackjps on February 24, 2016, 06:52:48 PM
Code: [Select]
About ncurses. I would think I need this for any fine tuning
of a monitor screen.  If I key in 'man ncurses' in a terminal
am I looking at the complete ncurses?
If not, where can I get the complete list?>

Bryants comment:
"In the directory where you got a clean build, you should have a file named demo64 without any extension. that file should be marked executable. You can run it using the command ./demo64 in the same directory."
Here's what I do: click on demo64 with no extension, right click in an open space and in the window that comes up I click on "Open a Terminal". This gives me a small
screen in a window called terminal. If I left click on demo64, it brings up a window
and an "execution" tab. Clicking on this tab does nothing.
Found this in ncurses:
 The  ncurses  library  permits  manipulation of data structures, called
       windows, which can be thought of as two-dimensional arrays  of  charac?
       ters representing all or part of a CRT screen.  A default window called
       stdscr, which is the size of the terminal screen, is supplied.   Others
       may be created with newwin.
I changed your program slightly:
   ;; lets create a child window
;   mov rcx, 50    ; x value
;   mov rdx, 10    ; y value
;   mov rsi, 5     ; 5 columns for 4 digits
;   mov rdi, 1     ; 1 line for 1 row of digits
;   call newwin
   mov rcx,0      ; x value
   mov rdx,0      ; y value
   mov rsi,5      ; 5 columns for 4 digits
   mov rdi,1      ; 1 line for 1 row of digits
   call newwin
This didn't cut the mustard. Still getting a terminal 1/4 sized window.

I'll take it 1 step at a time and try to get the screen to fill the
entire page.
Title: Re: beginner questions
Post by: Bryant Keller on February 26, 2016, 07:56:14 PM
About ncurses. I would think I need this for any fine tuning
of a monitor screen.  If I key in 'man ncurses' in a terminal
am I looking at the complete ncurses?
If not, where can I get the complete list?

These links should be kept if you do NCURSES development.

NCURSES Manual (http://invisible-island.net/ncurses/man/ncurses.3x.html)
NCURSE Frequently Asked Questions (http://invisible-island.net/ncurses/ncurses.faq.html)
GNU's NCURSES page (http://www.gnu.org/software/ncurses/)

Here's what I do: click on demo64 with no extension, right click in an open space and in the window that comes up I click on "Open a Terminal". This gives me a small
screen in a window called terminal. If I left click on demo64, it brings up a window
and an "execution" tab. Clicking on this tab does nothing.

Unlike on Windows, the terminal window is just another application, you can actually remove them and install different ones if you want (xterm, eterm, rxvt, xfce4-terminal, gnome-terminal, etc.). Your graphical environment and console mode applications aren't tied together and if you run a console mode program, the system won't just swap to a console and take over the screen. Console applications need to be specifically launched in a terminal (or from a terminal). If you want fullscreen mode, try my suggestion on the other forum. You'll need to switch between consoles using the ALT+CTRL+Fn keys.

Found this in ncurses:
 The  ncurses  library  permits  manipulation of data structures, called
       windows, which can be thought of as two-dimensional arrays  of  charac?
       ters representing all or part of a CRT screen.  A default window called
       stdscr, which is the size of the terminal screen, is supplied.   Others
       may be created with newwin.
I changed your program slightly:
Code: [Select]
   ;; lets create a child window
;   mov rcx, 50    ; x value
;   mov rdx, 10    ; y value
;   mov rsi, 5     ; 5 columns for 4 digits
;   mov rdi, 1     ; 1 line for 1 row of digits
;   call newwin
   mov rcx,0      ; x value
   mov rdx,0      ; y value
   mov rsi,5      ; 5 columns for 4 digits
   mov rdi,1      ; 1 line for 1 row of digits
   call newwin
This didn't cut the mustard. Still getting a terminal 1/4 sized window.

I'll take it 1 step at a time and try to get the screen to fill the
entire page.

The reason it didn't work is because that line has nothing to do with the background window. There are actually 2 windows at play in that example. The standard screen (stdscr) is the root window and it is created by:

Code: [Select]
   ;; initialize the curses library
   call initscr

   ;; was curses initialization successful?
   cmp rax, 0
   jne .CursesInitSuccessful

   ;; initialization failed, return FALSE
   STACK_RESTORE
   mov rax, FALSE
   ret

.CursesInitSuccessful:
   ;; save a copy of curses root window
   mov [hWindow], rax

I saved a copy of the stdscr handle in memory located at hWindow. The child window created by newwin is the rectangle than is holding the 4 characters you're inputing.

I'm not sure why you're not getting the proper display height/width. The stdscr is supposed to be automatically set to your terminal dimensions. This honestly sounds like a bug in your terminal emulator, try running xterm and test the program in that terminal emulator. If you don't have xterm or the command redirects to another terminal (some distro's do that, I hate that) then try it from the console (which I think you were going to do anyway).

Quote from: "shankle (MasmForum)" date=1456488181
On the NASM forum i'm lucky if I get 1 response per day to my questions.

One of the reasons you don't get immediate answers is because your posts are spread out, you're talking on two different forums across (so far) 3 different threads and your responses assume that everyone is able to follow you. This isn't the case. I rarely get on MasmForum except to message friends from the old AsmCommunity site. That said, if you're going to cross post, make sure you give all relevant information to your post. For example, your post on MasmForum doesn't explain what demo64 is, you just assume the people there know what your talking about, that's why I was the only one to respond. It's hard for anyone to answer questions when all the information isn't there.

Quote from: "shankle (MasmForum)" date=1456488181
With no books to study about the language and erroneous, outdated and
hard to find solutions, one wonders how anyone can program in NASM.

True, most books referring to Assembly Language target the 32-bit platform. With all the information targeting the 32-bit architecture, people find it easier to just start there using 32-bit environments in virtual machines or using backward compatibility mode, then later on (after they've gained basic programming skills) learn the conventions for 64-bit architectures from the Intel manual's.
Title: Re: beginner questions
Post by: jackjps on February 26, 2016, 08:03:28 PM
Code: [Select]
Hi Bryant,
Haven't read your last post yet but will.
I wanted you to see this stripped down version of your
program that just tries to put a blue screen on the monitor,
not the terminal. It puts a blue screen on the monitor filling
the same size as the terminal (1/4 of the screen)
I downloaded "xterm" and it did the same thing as the regular
terminal in Nasm. My problem is that I can't expect a user to
change to a console mode. I will try your suggestion and read
the 3 sites you gave me. Thanks.

;   2-26-2016 using NASM 64
;   Order of colors: BGR
;
; This is a stripped down version of your program.
; Trying to fill the screen of whatever monitor is
; in place in light blue.

; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf64 demo64.asm -o demo64.o
;  gcc -o demo64 demo64.o -lcurses

; Run Process:
;   ./demo64

   bits 64
   cpu IA64

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern atoi
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern keypad
   extern nonl
   extern cbreak
   extern echo
   extern has_colors
   extern start_color
   extern init_pair
   extern newwin
   extern endwin
   extern refresh
   extern wrefresh
   extern wgetnstr
   extern wbkgd

   extern LINES
   extern COLS

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h

   %define COLOR_BLACK     0
   %define COLOR_RED       1
   %define COLOR_GREEN     2
   %define COLOR_YELLOW    3
   %define COLOR_BLUE      4
   %define COLOR_MAGENTA   5
   %define COLOR_CYAN      6
   %define COLOR_WHITE     7
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define STACK_ALIGN sub rsp, 8
   %define STACK_RESTORE add rsp, 8

section .data

hWindow:       dq 0
hChildWindow:  dq 0
szUserInput:   db 0, 0, 0, 0, 0

; test code begin
  msg db      "got past clear_blue  "
; test code end

section .text
;;  do_init : nothing -> boolean .
;;  preform all of the applications initialization.
;;  when initialization was successful, hWindow will
;;  contain the curses screen handle and the return
;;  value will be TRUE. otherwise, it returns FALSE.

do_init:
   STACK_ALIGN

;;  setup an interrupt to terminate
   mov rsi,do_exit
   mov rdi,SIGINT
   call signal

;;  initialize the curses library
   call initscr

;;  was curses initialization successful?
   cmp rax,0
   jne .CursesInitSuccessful

;;  initialization failed, return FALSE
   mov rax,FALSE
   ret

.CursesInitSuccessful:
;;  save a copy of curses root window
   mov [hWindow],rax

;;  does this system support color terminals?
   call has_colors
   cmp rax,0
   jne .HasColorSupport

;;  No color support, return FALSE
   STACK_RESTORE
   mov rax,FALSE
   ret

.HasColorSupport:
   call start_color

;;  create our color pairs
;;  black foreground, blue background
   mov rdx,COLOR_BLUE
   mov rsi,COLOR_BLACK
   mov rdi,BLACK_ON_BLUE
   call init_pair

;;  if we reach this point, we have initialized successfully.
   STACK_RESTORE
   mov rax,TRUE
   ret

;;  do_exit : integer -> nothing .
;;  exit to the operating system.
do_exit:
   STACK_ALIGN

;;  refresh our screen
   call refresh

;;  shut down curses
   call endwin

;;  return to operating system
   push qword 0
   call exit
   add rsp,4

;;  we should never reach this point
   STACK_RESTORE
   ret

;;  clear_blue : nothing -> nothing .
;;  create a full screen of a light blue color.
clear_blue:
   STACK_ALIGN

;;  make our background blue
   mov rsi,COLOR_PAIR(BLACK_ON_BLUE)
   mov rdi,[hWindow]
   call wbkgd

   ;; refresh our screen
   mov rdi, [hWindow]
   call wrefresh
   STACK_RESTORE
   ret

;;   main : integer (string . string) -> integer .
;;   our program starts here.
main:
   STACK_ALIGN
   call do_init
   cmp rax,TRUE
   jne .done

;;  clear the screen to blue
   call clear_blue

; test code begin
    mov     rax,1   ; sys-write
    mov     rdi,1   ; standard output
    mov     rsi,msg
    mov     rdx,21  ; message length
    syscall         ; write message to screen
    mov     rax,60  ; sys_exit
    mov     rdi,0   ; error code
    syscall         ; exit
; test code end

.done:
   STACK_RESTORE
   xor rdi,rdi
   call do_exit
   ret
 
Title: Re: beginner questions
Post by: Bryant Keller on February 26, 2016, 08:29:12 PM
Hi Bryant,
Haven't read your last post yet but will.
I wanted you to see this stripped down version of your
program that just tries to put a blue screen on the monitor,
not the terminal
It puts a blue screen on the monitor filling the same size as the
terminal (1/4 of the screen)
Code: [Select]
;   2-26-2016 using NASM 64
;   Order of colors: BGR
;
; This is a stripped down version of your program.
; Trying to fill the screen of whatever monitor is
; in place in light blue.

; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf64 demo64.asm -o demo64.o
;  gcc -o demo64 demo64.o -lcurses

; Run Process:
;   ./demo64

   bits 64
   cpu IA64

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern atoi
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern keypad
   extern nonl
   extern cbreak
   extern echo
   extern has_colors
   extern start_color
   extern init_pair
   extern newwin
   extern endwin
   extern refresh
   extern wrefresh
   extern wgetnstr
   extern wbkgd

   extern LINES
   extern COLS

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h

   %define COLOR_BLACK     0
   %define COLOR_RED       1
   %define COLOR_GREEN     2
   %define COLOR_YELLOW    3
   %define COLOR_BLUE      4
   %define COLOR_MAGENTA   5
   %define COLOR_CYAN      6
   %define COLOR_WHITE     7
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define STACK_ALIGN sub rsp, 8
   %define STACK_RESTORE add rsp, 8

section .data

hWindow:       dq 0
hChildWindow:  dq 0
szUserInput:   db 0, 0, 0, 0, 0

; test code begin
  msg db      "got past clear_blue  "
; test code end

section .text
;;  do_init : nothing -> boolean .
;;  preform all of the applications initialization.
;;  when initialization was successful, hWindow will
;;  contain the curses screen handle and the return
;;  value will be TRUE. otherwise, it returns FALSE.

do_init:
   STACK_ALIGN

;;  setup an interrupt to terminate
   mov rsi,do_exit
   mov rdi,SIGINT
   call signal

;;  initialize the curses library
   call initscr

;;  was curses initialization successful?
   cmp rax,0
   jne .CursesInitSuccessful

;;  initialization failed, return FALSE
   mov rax,FALSE
   ret

.CursesInitSuccessful:
;;  save a copy of curses root window
   mov [hWindow],rax

;;  does this system support color terminals?
   call has_colors
   cmp rax,0
   jne .HasColorSupport

;;  No color support, return FALSE
   STACK_RESTORE
   mov rax,FALSE
   ret

.HasColorSupport:
   call start_color

;;  create our color pairs
;;  black foreground, blue background
   mov rdx,COLOR_BLUE
   mov rsi,COLOR_BLACK
   mov rdi,BLACK_ON_BLUE
   call init_pair

;;  if we reach this point, we have initialized successfully.
   STACK_RESTORE
   mov rax,TRUE
   ret

;;  do_exit : integer -> nothing .
;;  exit to the operating system.
do_exit:
   STACK_ALIGN

;;  refresh our screen
   call refresh

;;  shut down curses
   call endwin

;;  return to operating system
   push qword 0
   call exit
   add rsp,4

;;  we should never reach this point
   STACK_RESTORE
   ret

;;  clear_blue : nothing -> nothing .
;;  create a full screen of a light blue color.
clear_blue:
   STACK_ALIGN

;;  make our background blue
   mov rsi,COLOR_PAIR(BLACK_ON_BLUE)
   mov rdi,[hWindow]
   call wbkgd

   ;; refresh our screen
   mov rdi, [hWindow]
   call wrefresh
   STACK_RESTORE
   ret

;;   main : integer (string . string) -> integer .
;;   our program starts here.
main:
   STACK_ALIGN
   call do_init
   cmp rax,TRUE
   jne .done

;;  clear the screen to blue
   call clear_blue

; test code begin
    mov     rax,1   ; sys-write
    mov     rdi,1   ; standard output
    mov     rsi,msg
    mov     rdx,21  ; message length
    syscall         ; write message to screen
    mov     rax,60  ; sys_exit
    mov     rdi,0   ; error code
    syscall         ; exit
; test code end

.done:
   STACK_RESTORE
   xor rdi,rdi
   call do_exit
   ret
 

Let's break down some key points.

Code: [Select]
; test code begin
    mov     rax,1   ; sys-write
    mov     rdi,1   ; standard output
    mov     rsi,msg
    mov     rdx,21  ; message length
    syscall         ; write message to screen

Because we are working within ncurses, this will have unexpected results. You shouldn't be writing on standard output, instead you should be writing to root window provided by curses. This window is buffered and all the decorations (background color, etc.) occur when the root window is refreshed. If you want to write msg to the screen, you first should modify:

Code: [Select]
; test code begin
  msg db      "got past clear_blue  "
; test code end

To be defined like this:


Code: [Select]
; test code begin
  msg db      "got past clear_blue  ", 0
; test code end

Next, you'll want to use waddstr instead of the system call:

Code: [Select]
; test code begin
    mov rsi, msg
    mov rdi, [hWindow]
    call waddstr

Also, you'll need to add extern waddstr to the list of "Functions from the NCurses Library".

Code: [Select]
    mov     rax,60  ; sys_exit
    mov     rdi,0   ; error code
    syscall         ; exit
; test code end

Remember Frank talking about having to reset his screen, if you do this, that's what will happen. You need to let ncurses do some last minute things before closing out your program (like resetting your default terminal options). I handle this in the "do_exit" procedure. If you want to use the syscall version of exit, you should move that to the do_exit procedure and replace these lines with your syscall verison:

Code: [Select]
;;  return to operating system
   push qword 0
   call exit
   add rsp,4

That's a good idea since that's actually wrong anyway, the 64-bit calling convention uses EDI for the first parameter. The code from demo64.asm uses:

Code: [Select]
   ;; return to operating system
   mov rdi, 0
   call exit

Use either this one or your syscall version, but the current one is wrong.
Title: Re: beginner questions
Post by: jackjps on February 27, 2016, 02:07:46 PM
Hi Bryant,
I made the changes you last posted.
I have no idea if this library is on my computer.
;  libncurses-dev    - Developer's libraries for ncurses.
Maybe hwindow is not getting loaded

  your code:
;;  was curses initialization successful?
   cmp rax,0
   jne .CursesInitSuccessful
;;  initialization failed, return FALSE
   mov rax,FALSE
   ret
.CursesInitSuccessful:
;;  save a copy of curses root window
   mov [hWindow],rax
my comment: at this point I would think that rax has a "1" in it.
Is that correct???

I have this message after hwindow is loaded.
; test code begin.
;  msg2 db      "hwindow is loaded   ",0
    mov     rdi,[hWindow]
    mov     rsi,msg2
    call waddstr    ; write message to screen
; test code end

I can not test after initscr because I don't know how to
change the test code from hwindow to a  test of rax. It is
not loaded at the initscr call yet.

Please a little clarification:
I see so much on the internet of programmers using 80h, syscall and no ncurses.
Is ncurses something new or just better than the old way?
Title: Re: beginner questions
Post by: Bryant Keller on February 27, 2016, 11:34:49 PM
Hi Bryant,
I made the changes you last posted.
I have no idea if this library is on my computer.
;  libncurses-dev    - Developer's libraries for ncurses.

If GCC compiles the code without errors, then you have it.

Maybe hwindow is not getting loaded

  your code:
Code: [Select]
;;  was curses initialization successful?
   cmp rax,0
   jne .CursesInitSuccessful
;;  initialization failed, return FALSE
   mov rax,FALSE
   ret
.CursesInitSuccessful:
;;  save a copy of curses root window
   mov [hWindow],rax
my comment: at this point I would think that rax has a "1" in it.
Is that correct???

No, RAX contains a pointer to the stdscr structure, we save that in hWindow so we can access it later. All calls to ncurses functions that start with the letter 'w' (eg. waddstr, waddchr, wmove) require you to pass that pointer as the first argument.

I have this message after hwindow is loaded.
Code: [Select]
; test code begin.
;  msg2 db      "hwindow is loaded   ",0
    mov     rdi,[hWindow]
    mov     rsi,msg2
    call waddstr    ; write message to screen
; test code end
I can not test after initscr because I don't know how to
change the test code from hwindow to a  test of rax. It is
not loaded at the initscr call yet.

I'm confused; that is exactly what the code above does. Where the comment starts "was curses initialization successful?" the value of RAX should be the return value of the call to initscr. We check to see if that value is zero because initscr returns zero when it fails to initialize ncurses.  If you want to place an waddstr message, then you should do that after the last instruction of that code. HOWEVER, writing to a curses window is not like writing to your screen normally, it is back-buffered. Your changes won't show up until you call wrefresh on the handle in hWindow.

Code: [Select]
; Use Case:
;  - create a full screen of a light blue color.
;  - put a small rectangle on the screen in yellow.
;  - let the user enter 4 digits in black in that rectangle.
;  - read the 4 digits from the rectangle.

; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf64 demo64.asm -o demo64.o
;  gcc -o demo64 demo64.o -lcurses
;
; Run Process:
;   ./demo64


   bits 64

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern fputs ;; we'll need this for an error message without curses.
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern nodelay
   extern noecho
   extern nonl
   extern cbreak
   extern keypad
   extern has_colors
   extern start_color
   extern init_pair
   extern endwin
   extern refresh
   extern wrefresh
   extern wattron
   extern waddstr
   extern wgetch

   %define STDIN  0
   %define STDOUT 1
   %define STDERR 2

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h
   %define ERR  (-1) ; defined in curses.h

   %define COLOR_BLACK     0
   %define COLOR_YELLOW    3
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_YELLOW 1

   %define STACK_ALIGN sub rsp, 8
   %define STACK_RESTORE add rsp, 8

section .rodata

szNCursesHelloWorld: db "Hello, ncurses world!", 0
szNCursesInitFailed: db "ncurses initialization; failed.", 0

section .data

hWindow:       dq 0

section .text

;; do_init : nothing -> boolean .
;; preform all of the applications initialization.
;; when initialization was successful, hWindow will
;; contain the curses screen handle and the return
;; value will be TRUE. otherwise, it returns FALSE.
do_init:
   STACK_ALIGN

   ;; setup an interrupt to terminate
   mov rsi, do_exit
   mov rdi, SIGINT
   call signal

   ;; initialize the curses library
   call initscr

   ;; was curses initialization successful?
   cmp rax, 0
   jne .CursesInitSuccessful

      ;; initialization failed, return FALSE
      STACK_RESTORE
      mov rax, FALSE
      ret

.CursesInitSuccessful:
   ;; save a copy of curses root window
   mov [hWindow], rax

   ;; enable keyboard mapping
   mov rsi, TRUE
   mov rdi, [hWindow]
   call keypad

   ;; tell curses not to translate LF into CRLF on output
   call nonl

   ;; take input chars one at a time, no waiting for newline
   call cbreak

   ;; Don't wait on input from wgetch, we'll just poll on user input instead.
   call nodelay

   ;; disable character echoing
   call noecho

   ;; does this system support color terminals?
   call has_colors
   cmp rax, 0
   jne .HasColorSupport

      ;; No color support, return FALSE
      STACK_RESTORE
      mov rax, FALSE
      ret

.HasColorSupport:
   call start_color

   ;; create our color pairs
   ;; black foreground, yellow background
   mov rdx, COLOR_YELLOW
   mov rsi, COLOR_BLACK
   mov rdi, BLACK_ON_YELLOW
   call init_pair

   ;; if we reach this point, we have initialized successfully.
   STACK_RESTORE
   mov rax, TRUE
   ret

;; do_exit : integer -> nothing .
;; exit to the operating system.
do_exit:
   STACK_ALIGN

   ;; refresh our screen
   call refresh

   ;; shut down curses
   call endwin

   ;; return to operating system
   mov rdi, 0
   call exit

   ;; we should never reach this point
   STACK_RESTORE
   ret


;; main : integer (string . string) -> integer .
;; our program starts here.
main:
   STACK_ALIGN

   call do_init
   cmp rax, FALSE
   jne .initSuccess

      ;; do_init failed so let's display a message to the console
      ;; instead of the ncurses window (since it doesn't exist).
      mov esi, szNCursesInitFailed
      mov edi, STDERR
      call fputs

   jmp .done

.initSuccess:

   ;; At this point, ncurses's has successfully initialized and
   ;; hWindow contains a pointer to the stdscr structure.

   ;; Display our message in black text on a yellow background.
   mov esi, COLOR_PAIR(BLACK_ON_YELLOW)
   mov edi, [hWindow]
   call wattron

   mov esi, szNCursesHelloWorld
   mov edi, [hWindow]
   call waddstr

   ;; The last two commands wrote a string on the window buffer,
   ;; now we need to display that buffer on the screen.
   mov edi, [hWindow]
   call wrefresh

   ;; Now that we've displayed something on the screen, we should
   ;; wait for the user to hit any key. We set the user input to
   ;; nonblocking mode with (nodelay) earlier, so wgetch returns
   ;; a translated keycode from the user input, if the user hasn't
   ;; hit a key, it will immediately return ERR. We loop on this
   ;; until we get input from the user.
.getChar:
   mov edi, [hWindow]
   call wgetch

   cmp eax, ERR
   jne .getChar

   ;; once the user has it a key, we can now exit the application.
   ;; we only waited on user input so the message we displayed can
   ;; be read by the user.
.done:
   STACK_RESTORE
   xor rdi, rdi
   call do_exit
   ret

Please a little clarification:
I see so much on the internet of programmers using 80h, syscall and no ncurses.

You asked about doing colors on the screen, that's what ncurses is for. If you just want to display test, you don't need ncurses, you can just write to the screen using the 'write' system call. The int 80h stuff is related to 32-bit system calls, this was replaced by the opcode syscall on 64-bit systems.


Is ncurses something new or just better than the old way?

ncurses actually stands for "New Curses". Basically it's one of several implementations of the curses api, and the most common one in my experience. CURSES itself predates Linux and Windows systems, it goes back to the old AT&T UNIX platforms. So technically curses this is the old way.
Title: Re: beginner questions
Post by: jackjps on February 28, 2016, 10:42:35 AM
Thank you Bryant for your patience.
About "initscr".
If I understand correctly: initscr puts a zero in rax
if initscr fails and puts a pointer in rax if initscr is good.

I tried to run your new program and I got a segmentation fault.
section .rodata - is just a typo or does it make any difference?
Will continue looking to see if I can find what's causing it.

I am having no luck with "alt+ctrl+f1-f8". Where would I execute it?
Running Linux mint 17.3 rosa xfce
Title: Re: beginner questions
Post by: Bryant Keller on February 28, 2016, 05:45:04 PM
Thank you Bryant for your patience.
About "initscr".
If I understand correctly: initscr puts a zero in rax
if initscr fails and puts a pointer in rax if initscr is good.

I tried to run your new program and I got a segmentation fault.
section .rodata - is just a typo or does it make any difference?
Will continue looking to see if I can find what's causing it.

The .rodata section is a read-only data section. It's where you store your constant variables so there is no chance that the get changed. I mostly use it to store strings.

Disregard that last bit of code, I made some mistakes in it. That's the problem with me helping people with 64-bit stuff.. I don't have a 64-bit machine to test the code. I think I fixed the errors in the following code.

Code: [Select]
; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf64 hello64.asm -o hello64.o
;  gcc -o hello64 hello64.o -lcurses
;
; Run Process:
;   ./hello64


   bits 64

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern fputs ;; we'll need this for an error message without curses.
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern noecho
   extern nonl
   extern cbreak
   extern keypad
   extern has_colors
   extern start_color
   extern init_pair
   extern endwin
   extern refresh
   extern wrefresh
   extern wattron
   extern waddstr
   extern wgetch

   %define STDIN  0
   %define STDOUT 1
   %define STDERR 2

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h

   %define COLOR_BLACK     0
   %define COLOR_YELLOW    3
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_YELLOW 1

   %define STACK_ALIGN sub rsp, 8
   %define STACK_RESTORE add rsp, 8

section .rodata

szNCursesHelloWorld: db "Hello, ncurses world!", 0
szNCursesInitFailed: db "ncurses initialization; failed.", 0

section .data

hWindow:       dq 0

section .text

;; do_init : nothing -> boolean .
;; preform all of the applications initialization.
;; when initialization was successful, hWindow will
;; contain the curses screen handle and the return
;; value will be TRUE. otherwise, it returns FALSE.
do_init:
   STACK_ALIGN

   ;; setup an interrupt to terminate
   mov rsi, do_exit
   mov rdi SIGINT
   call signal

   ;; initialize the curses library
   call initscr

   ;; was curses initialization successful?
   cmp rax, 0
   jne .CursesInitSuccessful

      ;; initialization failed, return FALSE
      STACK_RESTORE
      mov rax, FALSE
      ret

.CursesInitSuccessful:
   ;; save a copy of curses root window
   mov [hWindow], rax

   ;; enable keyboard mapping
   mov rsi, TRUE
   mov rdi, [hWindow]
   call keypad

   ;; tell curses not to translate LF into CRLF on output
   call nonl

   ;; take input chars one at a time, no waiting for newline
   call cbreak

   ;; disable character echoing
   call noecho

   ;; does this system support color terminals?
   call has_colors
   cmp rax, 0
   jne .HasColorSupport

      ;; No color support, return FALSE
      STACK_RESTORE
      mov rax, FALSE
      ret

.HasColorSupport:
   call start_color

   ;; create our color pairs
   ;; black foreground, yellow background
   mov rdx, COLOR_YELLOW
   mov rsi, COLOR_BLACK
   mov rdi, BLACK_ON_YELLOW
   call init_pair

   ;; if we reach this point, we have initialized successfully.
   STACK_RESTORE
   mov rax, TRUE
   ret

;; do_exit : integer -> nothing .
;; exit to the operating system.
do_exit:
   STACK_ALIGN

   ;; refresh our screen
   call refresh

   ;; shut down curses
   call endwin

   ;; return to operating system
   mov rdi, 0
   call exit

   ;; we should never reach this point
   STACK_RESTORE
   ret


;; main : integer (string . string) -> integer .
;; our program starts here.
main:
   STACK_ALIGN

   call do_init
   cmp rax, FALSE
   jne .initSuccess

      ;; do_init failed so let's display a message to the console
      ;; instead of the ncurses window (since it doesn't exist).
      mov rsi, szNCursesInitFailed
      mov rdi, STDERR
      call fputs

   jmp .done

.initSuccess:

   ;; At this point, ncurses's has successfully initialized and
   ;; hWindow contains a pointer to the stdscr structure.

   ;; Display our message in black text on a yellow background.
   mov rsi, COLOR_PAIR(BLACK_ON_YELLOW)
   mov rdi, [hWindow]
   call wattron

   mov rsi, szNCursesHelloWorld
   mov rdi, [hWindow]
   call waddstr

   ;; The last two commands wrote a string on the window buffer,
   ;; now we need to display that buffer on the screen.
   mov rdi, [hWindow]
   call wrefresh

   ;; Now that we've displayed something on the screen, we should
   ;; wait for the user to hit any key.

   mov rdi, [hWindow]
   call wgetch

   ;; once the user has it a key, we can now exit the application.
   ;; we only waited on user input so the message we displayed can
   ;; be read by the user.
.done:
   STACK_RESTORE
   mov rdi, 0
   call do_exit
   ret

I am having no luck with "alt+ctrl+f1-f8". Where would I execute it?
Running Linux mint 17.3 rosa xfce

At the bottom left side of your keyboard should be keys labeled CTRL and ALT. At the top of you keyboard should be keys labeled F1, F2, F3, ... F12. Most Linux and BSD systems I use map the key sequence CTRL+ALT+F1 to the first console, CTRL+ALT+F2 to the second, and so on until around CTRL+ALT+F7 or CTRL+ALT+F8 which will usually be running your GUI (in your case XFCE).

The + means that you push each of the keys at the same time. Make a "V" with the fingers on your left hand and hold down both CTRL and ALT. While keeping them pressed, take your right hand and touch the F1 key. This is what's meant by CTRL+ALT+F1.
Title: Re: beginner questions
Post by: jackjps on February 28, 2016, 06:41:24 PM
Thanks Bryant,
That worked. Got a black screen, with a yellow rectangle,
the message and a terminal sized screen.
Left out a comma. Fixed it and everything ran fine.

In Windows I frequently used Ctrl+Alt+Delete.
I go into /home/jack/nasmfld. Then I click on demo64.exe.
Go to a clear space and RC and click on open in terminal.
Then I do alt+ctrl+f8. I get a screen with the cursor setting
at Jack@jack-myheadache. I would think at this point I
need to change back into /home/jack/nasmfld to execute
demo64. I don't know how to do that.

 
Title: Re: beginner questions
Post by: Bryant Keller on February 28, 2016, 08:31:18 PM
Thanks Bryant,
That worked. Got a black screen, with a yellow rectangle,
the message and a terminal sized screen.
Left out a comma. Fixed it and everything ran fine.

Great, glad it works. :)

In Windows I frequently used Ctrl+Alt+Delete.

Yeah, it's the same kind of key combinations. :)

I go into /home/jack/nasmfld. Then I click on demo64.exe.
Go to a clear space and RC and click on open in terminal.

The "Open in Terminal" option is going to open the current directory in a virtual terminal emulator (VTE). If you're just wanting to make your VTE window to run in full screen mode, you just use F11(this is assuming your using xfce's VTE) once the VTE is running and it'll expand to fill the screen.

Then I do alt+ctrl+f8. I get a screen with the cursor setting
at Jack@jack-myheadache. I would think at this point I
need to change back into /home/jack/nasmfld to execute
demo64. I don't know how to do that.

The use of CTRL+ALT+F1 switches you to an actual console (not a terminal). At the console, you'll login and be put into your home directory. At this point, you'll need to move around in text mode. If you're familiar with DOS, you might find the Linux/Unix for DOS Users (http://www.yolinux.com/TUTORIALS/unix_for_dos_users.html) web-page helpful. If not, then maybe you should stick to the VTE until you become better acquainted with working within the shell.

The big confusion here is that many uses think that "console" and "virtual terminal" are just two words that mean the same thing. That's not true, these are very different. The console is an application that lets you execute commands on a local Linux/UNIX system and "virtual terminals" are programs that simulate the operation of a real terminal. Your "virtual terminal" connects to the console and gives you access to it from within your GUI (or possibly from another network). A better way to think of this is, from a Windows user perspective, DOS is a console and HyperTerminal or PuTTY are virtual terminals.

Before you continue with your programming studies, get to know Linux itself. The following links are listed in increasing level of difficulty, I suggest working your way down the list.

Title: Re: beginner questions
Post by: jackjps on February 28, 2016, 09:25:59 PM
Thanks again Bryant.
Cut my baby teeth on DOS. It's an old friend.
However, need to do that reading on Linux.

To get the wide screen I clicked on the xfce terminal icon.
Did cd /home/jack/nasmfld. Hit enter.
Keyed in ./demo64 and voila, got a full screen. :)

Only question I have about all this is, it will not work
for a user. They want to run an ex: "demo64.exe" and be
in the full screen without doing anything else....

Title: Re: beginner questions
Post by: Bryant Keller on February 29, 2016, 12:20:11 AM
Thanks again Bryant.
Cut my baby teeth on DOS. It's an old friend.
However, need to do that reading on Linux.

To get the wide screen I clicked on the xfce terminal icon.
Did cd /home/jack/nasmfld. Hit enter.
Keyed in ./demo64 and voila, got a full screen. :)

Awesome :)

Only question I have about all this is, it will not work
for a user. They want to run an ex: "demo64.exe" and be
in the full screen without doing anything else....

Pretty much all Linux users will expect text mode applications to be ran either in the console or a terminal. Very few applications take over fullscreen on Linux and those are usually based around graphics frameworks like SDL or OpenGL. If you want the user to just double-click and get a terminal you need to develop a bash script to go along with your application that loads your program in a new terminal window. Create a file called "demo64.sh" and put the following in it:

Code: [Select]
#!/bin/sh
x-terminal-emulator -e ./demo64

Make that file executable with the command chmod +x demo64.sh and then from your GUI, double click that file. It should create a new xterm instance that the command runs it. Since you're using xfce, you could also opt to create a demo.desktop file that contains:

Code: [Select]
[Desktop Entry]
Type=Application
Terminal=true
Name=Demo64
Comment=A simple 64-bit NASM demo.
Icon=
Exec=./demo64
Path=

When you view this file from xfce (and a few others) GUI, it shows up as Demo64 with a tooltip of "A simple 64-bit NASM demo.", When you double click the file it runs in a terminal and you can even customize an icon for the file. You should note however, that "Exec=" needs to reference your executable exactly, so if you move the demo64.desktop file out of the same directory, it'll probably stop working, unless you use a full path name.
Title: Re: beginner questions
Post by: jackjps on February 29, 2016, 12:52:17 PM
Code: [Select]
HI Bryant,
1. The following pretty much lost me.
EX: I read the "man chmod" and didn't understand it.
So I am not able to fill this out "chmod +x demo64.sh".

2. The next example. Am I supposed  to fill out those fields or just
use it as is???
Which one should I use?

3.
I need to make sure that the user only enters
digits in demo64. I read the man pages on these two calls
and again I didn't understand the explanation. How do you
know what to put where? Have no idea how to enter the x/y
coordinates for placing a message.
;------------------------------------------------
;   3-1-2016 using NASM 64
;   Order of colors: BGR
;
; Bryants goodies
; Use Case:
;  - create a full screen of a light blue color.
;  - put a small rectangle on the screen in yellow.
;  - let the user enter 4 digits in black in that rectangle.
;  - read the 4 digits from the rectangle.

; Dependencies:
;  libc-dev          - GNU C library.
;  libncurses-dev    - Developer's libraries for ncurses.

; Build Process:
;  nasm -f elf64 demo64.asm -o demo64.o
;  gcc -o demo64 demo64.o -lcurses

; Run Process:
;   ./demo64

   bits 64
   cpu IA64

   global main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the Standard C Library
   extern signal
   extern atoi
   extern exit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions from the NCurses Library
   extern initscr
   extern keypad
   extern nonl
   extern cbreak
   extern echo
   extern has_colors
   extern start_color
   extern init_pair
   extern newwin
   extern endwin
   extern refresh
   extern waddstr
   extern wattron
   extern wrefresh
   extern wgetch
   extern wgetnstr
   extern wbkgd

   extern LINES
   extern COLS

   %define SIGINT 2  ; defined in signal.h
   %define TRUE   1  ; defined in curses.h
   %define FALSE  0  ; defined in curses.h
   %define STDERR 2

   %define COLOR_BLACK     0
   %define COLOR_RED       1
   %define COLOR_GREEN     2
   %define COLOR_YELLOW    3
   %define COLOR_BLUE      4
   %define COLOR_MAGENTA   5
   %define COLOR_CYAN      6
   %define COLOR_WHITE     7
   %define COLOR_PAIR(n) ((n) << (8))

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define BLACK_ON_BLUE   1
   %define BLACK_ON_YELLOW 2

   %define STACK_ALIGN sub rsp, 8
   %define STACK_RESTORE add rsp, 8

section .data

hWindow:       dq 0
hChildWindow:  dq 0
szUserInput:   db 0, 0, 0, 0, 0
uinputerr      db "only digits may be entered - enter again",0

section .text
;    global _start    ;??  bryant said these are included in the "c" lib
;_start:              ;??

;;  do_init : nothing -> boolean .
;;  preform all of the applications initialization.
;;  when initialization was successful, hWindow will
;;  contain the curses screen handle and the return
;;  value will be TRUE. otherwise, it returns FALSE.

do_init:
   STACK_ALIGN

;;  setup an interrupt to terminate
   mov rsi,do_exit
   mov rdi,SIGINT
   call signal

;;  initialize the curses library
   call initscr

;;  was curses initialization successful?
   cmp rax,0
   jne .CursesInitSuccessful

;;  initialization failed, return FALSE
   mov rax,FALSE
   ret

.CursesInitSuccessful:
;;  save a copy of curses root window
   mov [hWindow],rax

;;  enable keyboard mapping
   mov rsi,TRUE
   mov rdi,[hWindow]
   call keypad

;;  tell curses not to translate LF into CRLF on output
   call nonl

;;  take input chars one at a time, no waiting for newline
   call cbreak

;;  enable echoing of input
   call echo

;;  does this system support color terminals?
   call has_colors
   cmp rax,0
   jne .HasColorSupport

;;  No color support, return FALSE
   STACK_RESTORE
   mov rax,FALSE
   ret

.HasColorSupport:
   call start_color

;;  create our color pairs
;;  black foreground, blue background
   mov rdx,COLOR_BLUE
   mov rsi,COLOR_BLACK
   mov rdi,BLACK_ON_BLUE
   call init_pair

;;  black foreground, yellow background
   mov rdx,COLOR_YELLOW
   mov rsi,COLOR_BLACK
   mov rdi,BLACK_ON_YELLOW
   call init_pair

;;  lets create a child window
   mov rcx,50    ; x value
   mov rdx,10    ; y value
   mov rsi,5     ; 5 columns for 4 digits
   mov rdi,1     ; 1 line for 1 row of digits
   call newwin
   mov [hChildWindow],rax

;;  if we reach this point, we have initialized successfully.
   STACK_RESTORE
   mov rax,TRUE
   ret

;;  do_exit : integer -> nothing .
;;  exit to the operating system.
do_exit:
   STACK_ALIGN

;;  refresh our screen
   call refresh

;;  shut down curses
   call endwin

;;  return to operating system
   mov rdi,0
   call exit

;;  we should never reach this point
   STACK_RESTORE
   ret

;;  clear_blue : nothing -> nothing .
;;  create a full screen of a light blue color.
clear_blue:
   STACK_ALIGN

;;  make our background blue
   mov rsi,COLOR_PAIR(BLACK_ON_BLUE)
   mov rdi,[hWindow]
   call wbkgd

;; refresh our screen
   mov rdi, [hWindow]
   call wrefresh
   STACK_RESTORE
   ret

;;  draw_child_window : nothing -> nothing .
;;  put a small rectangle on the screen in yellow.
draw_child_window:
   STACK_ALIGN

;;  make our background yellow
   mov rsi,COLOR_PAIR(BLACK_ON_YELLOW)
   mov rdi,[hChildWindow]
   call wbkgd

;;  refresh our child window
   mov rdi,[hChildWindow]
   call wrefresh
   STACK_RESTORE
   ret

;;   get_user_input : nothing -> integer.
;;   let the user enter 4 digits in black in the rectangle.
get_user_input:
   STACK_ALIGN

;;   get user input
;;   here I am trying to test the input from the user for valid
;;   digits. The error message should go on the same line as the
;;   yellow rectangle. This bad code gives the error message at
;;   x-0,y-0. The yellow rectangle is not cleared for new input. 
.n1:
   mov rdx,4
   mov rsi,szUserInput
   mov rdi,[hChildWindow]
   call wgetnstr      ; reads all 4 characters good or bad
   mov rsi,szUserInput    ; check user input for digits
   mov ah,3
.n2:
   cmp ah,3     ; process 4 digits
    jg .out1    ; good input
   mov al,[rsi]
   cmp al,0
    jl .err1
   cmp al,9   
    jg .err1
   inc ah
   inc rsi
    jmp .n2

.err1:
   ;; Display error message in black text on a yellow background.
   mov rsi,COLOR_PAIR(BLACK_ON_YELLOW)
   mov rcx,5     ;???? x value
   mov rdx,10    ;????? y value
   mov rdi, [hWindow]
   call wattron

;uinputerr      db "only digits may be entered - start over",0
   mov rsi,uinputerr
   mov rdi, [hWindow]
   call waddstr

   ;; The last two commands wrote a string on the window buffer,
   ;; now we need to display that buffer on the screen.
   mov rdi, [hWindow]
   call wrefresh

   call draw_child_window
    jmp .n1

.out1:
;;   convert string to integer
;;   rdi, rsi, rdx, rcx, r8, r9
   mov rdi,szUserInput
   call atoi
   STACK_RESTORE
   ret

;;   main : integer (string . string) -> integer .
;;   our program starts here.
main:
   STACK_ALIGN
   call do_init
   cmp rax,TRUE
   jne .done

;;  clear the screen to blue
   call clear_blue

;;  draw yellow window
   call draw_child_window

;;  get user input
   call get_user_input

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;; At this point in our code, the number we ;;
   ;; entered into our child window is in the  ;;
   ;; RAX register. We can now use it for any- ;;
   ;; thing we want.                           ;;
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.done:
   STACK_RESTORE
   xor rdi,rdi
   call do_exit
   ret








 
Title: Re: beginner questions
Post by: Bryant Keller on March 02, 2016, 09:47:29 PM
HI Bryant,
1. The following pretty much lost me.
EX: I read the "man chmod" and didn't understand it.
So I am not able to fill this out "chmod +x demo64.sh".

Unlike Windows, Linux doesn't care what a filename's extension is. Linux determines if a program is executable or not based on a series of attributes that are attached to the file. These attributes are modified using chmod. If you want to make a file eXecutable, you give it the x attribute. To add an attribute to a file you use the + (plus) sign, and to remove it, you use the - (minus) sign. So chmod +x demo64.sh adds the executable attribute to the demo64.sh file. Once marked as executable, it can be ran like a program.

2. The next example. Am I supposed  to fill out those fields or just
use it as is???
Which one should I use?

I have no clue what your talking about here. The examples I've been giving you have just been to give you an idea about code you've been talking about. The first example was almost exactly what you said you were working on. The others were just to expand on questions you've asked. The most recent example was a basic hello world application which displayed an error using fputs when ncurses failed to initialize to show how you should handle that message instead of trying to write to the ncurses screen that didn't initialize. ;)

3.
I need to make sure that the user only enters
digits in demo64. I read the man pages on these two calls
and again I didn't understand the explanation.

Well, there are two ways to go about this, you can create your own wgetnstr routine using wgetch which limits user input to only digits. Or, when wgetnstr returns a string, you can then check the contents of the string to make sure it's a valid number and report an error to the screen. How you handle this is totally up to you.

How do you
know what to put where?

I referenced the documents I've linked you too. Most of them contains simple examples and will give you a basic understanding of how to work with curses. Until this thread, I had never used curses from assembly. Turns out, it's not that difficult.  ;D

Have no idea how to enter the x/y
coordinates for placing a message.

You move your cursor using the wmove command. The wmove procedure moves the cursor to a line number 'y' and a column 'x' relative to the windows origin. That last part makes it a bit confusing because if you are using wmove in a child window that's on line 4 column 3, then using wmove on that window with y=2 and x=1, the cursor would actually be on the screen at line 6 column 4. But working with the root window, the coordinates would be relative to the screen and should be easy enough to use, like so:

Code: [Select]
mov rdx, [x_val]
mov rsi, [y_val]
mov rdi, [hWindow]
call wmove
Title: Re: beginner questions
Post by: jackjps on March 04, 2016, 05:03:50 PM
Hi Bryant,
I'm still having problems with your last post. I will put that aside
for now and continue trying to complete my 1st program.
I have read the man page about "getmaxyx" and don't understand
the format of the instruction.

 void getmaxyx(WINDOW *win, int y, int x)

For instance what does void do?
what are the () for?
what goes where "window" is.
I assume the *win is stdscr

What I need is to get the number of columns on a monitor.
Title: Re: beginner questions
Post by: Frank Kotler on March 04, 2016, 09:10:34 PM
Hi jackjps,

"void" just advises the compiler not to use the returned eax/rax for anything. You shouldn't either, of course. The '()"s are just 'cause C programmers like 'em. The "*win" is presumably the "handle" of the window you're enquiring about - either the root window or the child window.

I'm quite puzzled by how a function that returns "void" can "get" anything. I could see it if you were passing the address of x and y, but that's not what it says. RTFM solves the puzzle:

http://invisible-island.net/ncurses/man/curs_getyx.3x.html

see down where it says NOTES? This puppy is a macro, and the "address of" indicator(s) are hidden - you do want to pass the address of x and y to be filled in. Gotta love this high-level shtuff! :)

Hope that helps until Bryant can get to you.

Best,
Frank

Title: Re: beginner questions
Post by: Bryant Keller on March 04, 2016, 11:23:05 PM
I'm still having problems with your last post. I will put that aside
for now and continue trying to complete my 1st program.
I have read the man page about "getmaxyx" and don't understand
the format of the instruction.

 void getmaxyx(WINDOW *win, int y, int x)

This is where things get complicated for working with C libraries under assembly. Unfortunately, C macros look just like C functions so sometimes it's hard to differentiate them unless you read the headers yourself. What makes it worse is, the macros usually make use of high level constructs which means they should actually be multi-line macros in assembly where (you might think you could just use a %define).


What I need is to get the number of columns on a monitor.

That hWindow we've been passing around is actually a data structure that holds information about the window's coordinates and other stuff i might need later on. NCURSES provides us with a convenience in the form of LINES and COLS. These are variables which old the maximum number of LINES and COLS of the current window. You'll notice that on earlier examples I was including these with:

Code: [Select]
   extern LINES
   extern COLS

The problem with these variables is that if you resize the window, these variables won't reflect the change. They are only defined once the program starts. This lead to the NCURSES header including the macro you've looked up there. Since implementing an exact clone of that macro would introduce a lot of code (specifically detecting our parameter types and ensuring we properly write to either memory or register correctly, etc) I decided to implement two new macros that just access the contents of the structure for you.

Code: (get_max_coord) [Select]
;; get_max_coord : window_handle -> { x y }
;; Obtains the max X and Y coordinates from a window handle
;; and returns the maximum X coordinate in rax and the maximum
;; Y coordinate in rbx.
%macro get_max_coord 1
push rsi
mov rsi, %1
xor rax, rax
xor rbx, rbx
mov ax, [rsi + 6]
mov bx, [rsi + 4]
pop rsi
%endmacro

Code: (get_cur_coord) [Select]
;; get_cur_coord : window_handle -> { x y }
;; Obtains the current X and Y coordinates from a window handle
;; and returns the current X coordinate in rax and the current
;; Y coordinate in rbx.
%macro get_cur_coord 1
push rsi
mov rsi, %1
xor rax, rax
xor rbx, rbx
mov ax, [rsi + 2]
mov bx, [rsi]
pop rsi
%endmacro

The actual data structure uses "short" integers for the coordinate variables so they are 16-bits (even on 64-bit machines). These macros return the coordinates in the RAX and RBX registers so if you you are using those variables in your code, be sure to save them before calling these macros.
Title: Re: beginner questions
Post by: jackjps on March 06, 2016, 02:42:08 PM
          3-6-2016
Hi Bryant,
A few more of my dumb questions Please.
Having trouble editing the input data from the user.
It's my lack of knowledge of NASM.

hWindow:       dq 0
hChildWindow:  dq 0
szUserInput:   db 0, 0, 0, 0, 0
Why the colon after items in the Data section????

You defined szUserInput as follows:
  szUserInput: db 0,0,0,0,0
I am used to something like
  szUserInput db '    ',0
  If the user enters this data '1234'
  is it coded as 31,32,33,34 OR
  as f1,f2,f3,f4?

All the input fields must be digits.
1st two can not be greater than 22.
2nd two can not be greater than 08.

Is there such a thing as a "struct" in NASM?
How do you reference each byte in NASM?
 can it be done this way:
  xor rsi,rsi
.t1:
  mov ch,byte [szUserInput+rsi]
  inc rsi
  jmp .t1 etc......
 Thanks
 
Title: Re: beginner questions
Post by: Frank Kotler on March 07, 2016, 04:30:08 AM
Hi jackjps,

I can answer some of this...

Quote

hWindow:       dq 0
hChildWindow:  dq 0
szUserInput:   db 0, 0, 0, 0, 0
Why the colon after items in the Data section????
Optional, after a label defining a variable. If the label is the only thing on the line. Nasm will generate a suppressible warning.

Quote
  If the user enters this data '1234'
  is it coded as 31,32,33,34
31h, 32h, 33h, 34h

Quote
All the input fields must be digits.
1st two can not be greater than 22.
2nd two can not be greater than 08.
You'll have to check those "by hand".

Nasm knows "struct", but spells it "struc". See:
http://www.nasm.us/doc/nasmdoc4.html#section-4.12.10
Note that "struc" only defines a structure, does not allocate any memory. Use "istruc" to allocate an instance (if you need to). The NASMX package includes "xstruc", which is somewhat more flexible, allowing nested structures and unions.

Code: [Select]
  xor rsi,rsi
.t1:
  mov ch,byte [szUserInput+rsi]
  inc rsi
  jmp .t1
that's fine, or as you had it before the edit:
Code: [Select]
$define B byte

  xor rsi,rsi
.t1:
  mov ch,B[szUserInput+rsi]
  inc rsi
  jmp .t1
Since the register cl determines the size of the operation, we don't really need to say "byte" at all. May make it clearer for us humans, but Nasm knows. :)

Best,
Frank



Title: Re: beginner questions
Post by: jackjps on March 07, 2016, 02:21:02 PM
Thanks Frank for responding,
I need a way to view all the 64-bit registers
without going into any debug stuff I know nothing about.
Does ncurses help any with that?
Title: Re: beginner questions
Post by: Frank Kotler on March 07, 2016, 04:43:10 PM
I think the correct answer to this is to learn  gdb. I don't "like" gdb much, so I haven't learned it very well, so I don't "like" it much. This is not a good plan!

However, you can display a 64-bit register the same as displaying any other number. That is, "just call printf" or do it in real assembly language. I presume you'll want it in hex. All the 64-bit registers is going to make quite a screenful of numbers. I think "ncurses" will offer some tricks to arrange it all neatly on the screen, but I doubt if it has printf-like capabilities. I dunno, you're the one who's reading the ncurses manual. That library from Soffian surely has such a routine. Even though I haven't done it, my advice is to learn to run gdb.

Best,
Frank

Title: Re: beginner questions
Post by: Bryant Keller on March 10, 2016, 01:14:53 AM
I agree with Frank. GDB is the way to go, it's text based but it's the most effective debugger on linux/bsd systems. If you absolutely *need* a GUI for your debugger, GNU's DDD program is nice, but has an even steeper learning curve than GDB itself. I used to like Insight debugger, but for some reason it was removed from the debian repositories and I'm too lazy to download and build it from the developer's website.  :-[
Title: Re: beginner questions
Post by: jackjps on March 13, 2016, 03:07:41 PM
I like to keep my program files separate from any OS.
OSes: Linux mint 17.3 rosa excp 64-bit and windows 7 pro 64-bit.
These OSes are on a separate SSD drive.
I do this on a 1T HD.  EX: masm32, GoAsm and now NASM.
If the unexpected happens my program files are safe.
I also back up these files regularly.

I can execute the masm32 and GoAsm program from the HD
with no problems...
Today I tried to do the same thing with my demo64 NASM program.
This is what happened:  "bash ./demo64: permission denied".
Thanks for any help...
Title: Re: beginner questions
Post by: Bryant Keller on March 13, 2016, 11:10:05 PM
I like to keep my program files separate from any OS.
OSes: Linux mint 17.3 rosa excp 64-bit and windows 7 pro 64-bit.
These OSes are on a separate SSD drive.
I do this on a 1T HD.  EX: masm32, GoAsm and now NASM.
If the unexpected happens my program files are safe.
I also back up these files regularly.

I can execute the masm32 and GoAsm program from the HD
with no problems...
Today I tried to do the same thing with my demo64 NASM program.
This is what happened:  "bash ./demo64: permission denied".
Thanks for any help...

How comfortable are you with Linux configuration files? Sounds to me like your 1T HD is being mounted with the noexec bit. You should be able to change "noexec" to "exec" in the /etc/fstab file, but I'd hate for you to accidentally cripple your system by editing the wrong one.

As a temporary solution, from the shell prompt, you can run sudo mount -o remount,exec /path/to/partition where /path/to/partition is the actual location of your partition. After doing that, you should try to use the ./demo64 command again and if it runs, that's your problem. You'll have to read up on editing the /etc/fstab file (or possibly just use that above command every time you want to run something from that drive)
Title: Re: beginner questions
Post by: jackjps on March 14, 2016, 12:49:24 AM
HI Bryant,
This what I got when I ran what you suggested:
jack@jack-myheadache ~ $ sudo mount -o remount,exec /media/jack/nasm/nasmfld
[sudo] password for jack:
mount: can't find /media/jack/nasm/nasmfld in /etc/fstab or /etc/mtab
jack@jack-myheadache ~ $

I have no idea where the /media came from but when I go to the place where the
./demo64 program is located on the HD, that is the address I see.
I really need to do this your other way as I would like to work off the HD if I can.
But you are right, I can't take the chance at my learning level and mess up
the computer.
Title: Re: beginner questions
Post by: Bryant Keller on March 15, 2016, 08:43:15 AM
The /media directory is where your partitions are mounted. Instead of that full path, try sudo mount -o remount,exec /media/jack
Title: Re: beginner questions
Post by: jackjps on March 15, 2016, 10:23:36 AM
Code: [Select]
Thanks for responding Bryant,
This is what I got.....

jack@jack-myheadache ~ $ sudo mount -o remount,exec /media/jack
[sudo] password for jack:
mount: can't find /media/jack in /etc/fstab or /etc/mtab
jack@jack-myheadache ~ $
;***************************************************************
Generally I want the whole screen to be Blue and it is.
All heading messages are in White and it is.
I want any error messages to be in say Yellow.
So the problem is how to make just the error messages Yellow
and leave the headings etc. in White? I tried adding an init_pair
Yellow/Blue and all the screen messages became Yellow.
I tried adding the init_pair where I wrote the error message
and it still made everything yellow.
Hope this makes sense....
Title: Re: beginner questions
Post by: Bryant Keller on March 16, 2016, 11:44:39 PM
Generally I want the whole screen to be Blue and it is.
All heading messages are in White and it is.
I want any error messages to be in say Yellow.
So the problem is how to make just the error messages Yellow
and leave the headings etc. in White? I tried adding an init_pair
Yellow/Blue and all the screen messages became Yellow.
I tried adding the init_pair where I wrote the error message
and it still made everything yellow.
Hope this makes sense....

The init_pair creates a new color index, the problem is we use wbkgd to set the color attribute for the whole window (which is usually how we do this). However, as you've discovered, there are times you want different color text on the same window.  :)

Luckily, NCurses has a function for that too. It's called, wchgat and the manual page on it is kinda cryptic. What you'll need to do is use the get_cur_coord macro just before you write your error message to the screen, and make sure you save the coordinates. After you write the string, use wmove to return to the coordinates you just saved. Once you're at the beginning of the string you want to make a different color, you then call wchgat to change the color and attributes of the string you just wrote.

Code: (int wchgat(WINDOW *win, int n, attr_t attr, short color, const void *opts)) [Select]
mov r8, 0               ; curses requires the "opts" parameter for future features that aren't currently implemented. so we just set it to 0.
mov rcx, YELLOW_ON_BLUE ; or whatever you named the color pair index using init_color
mov rdx, 0              ; the string attribute; 0 for normal, and 200000h for bold
mov rsi, szMessage_len  ; the length of the error message you printed.
mov rdi, [hWindow]      ; the window your string was printed on.
call wchgat

If you can't get it working with the above, post what you've got so far and I'll try to help. :)
Title: Re: beginner questions
Post by: jackjps on March 17, 2016, 01:15:25 PM
Code: [Select]
            3-17-2016
Hi Bryant,
This is what I got from my code below:
#1...........
jack@jack-myheadache ~/nasmfld $ nasm -f elf64 demo64.asm -o demo64.o
jack@jack-myheadache ~/nasmfld $ gcc -o demo64 demo64.o -lcurses
demo64.o: In function `get_user_input.err1':
demo64.asm:(.text+0x4b8): undefined reference to `get_cur_coord'
collect2: error: ld returned 1 exit status
jack@jack-myheadache ~/nasmfld $

   extern get_cur_coord    ; have no idea how or where to define this
   extern wchgat
   %define BLACK_ON_YELLOW 2

   call get_cur_coord
   mov r8, 0        ; curses requires the "opts" parameter for future features
                    ; that aren't currently implemented. so we just set it to 0.
   mov rcx, BLACK_ON_YELLOW ; or whatever you named the color pair index using
                    ; init_color
   mov rdx, 0       ; the string attribute; 0 for normal, and 200000h for bold
   mov rsi,42       ; the length of the error message you printed.
   mov rdi, [hWindow]      ; the window your string was printed on.
   call wchgat

;  call draw_child_window3
   mov rdx,50    ;  X
   mov rsi,11    ;  Y
;   mov rdi,[hChildWindow3]
   mov rdi,[hWindow]
   call wmove
;*****************

#2................
also never got this to work.
trying to run NASM from a HD not containing the OS.
jack@jack-myheadache ~ $ sudo mount -o remount,exec /media/jack/nasm/nasmfld
[sudo] password for jack:
mount: can't find /media/jack/nasm/nasmfld in /etc/fstab or /etc/mtab
jack@jack-myheadache ~ $
; *****************

#3...................
In MASM32 we have macro called "ATODW".
It converts a decimal string into a dw value.
CkBal db  '     4321',0
mathhold dd 0
I thought this was what "atoi" did....
more about this problem below.

; the user keys in "aa" incorrectly

hChildWindow   dq 0
msg                   dw 0   ; converted user input ??
szUserInput       db '  ',0

   mov rdx,2
   mov rsi,szUserInput
   mov rdi,[hChildWindow]
   call wgetnstr      ; reads 2 characters good or bad

;;   convert string to integer
   mov rdi,szUserInput
   call atoi   ; result in rax

   mov [msg],ax     ; preserve keyed in value ??
   cmp byte[msg+1],016h  ; This does not work!!!!!!!!!
                         ; value should not be > 22 decimal
    jg .err1
    jmp .out1               ; good input

; never gets here.............
.err1:
   call draw_child_window3
   mov rdx,50    ;  X
   mov rsi,11    ;  Y
   mov rdi,[hChildWindow3]
   call wmove
;msg6       db 'value keyed in is invalid - reenter ',0
   mov rsi,msg6
   mov rdi,[hChildWindow3]
   call waddstr

;;   The command wrote a string in the window buffer,
;;   now we need to display the buffer on the screen.
   mov rdi,[hChildWindow3]
   call wrefresh

Title: Re: beginner questions
Post by: Bryant Keller on March 17, 2016, 11:03:49 PM
            3-17-2016
Hi Bryant,
This is what I got from my code below:
Code: [Select]
jack@jack-myheadache ~/nasmfld $ nasm -f elf64 demo64.asm -o demo64.o
jack@jack-myheadache ~/nasmfld $ gcc -o demo64 demo64.o -lcurses
demo64.o: In function `get_user_input.err1':
demo64.asm:(.text+0x4b8): undefined reference to `get_cur_coord'
collect2: error: ld returned 1 exit status
jack@jack-myheadache ~/nasmfld $

get_cur_coord isn't a procedure you call, it's a macro that I gave you earlier in the thread (http://forum.nasm.us/index.php?topic=2204.msg9799#msg9799).

Code: [Select]
   extern get_cur_coord    ; have no idea how or where to define this
   extern wchgat
   %define BLACK_ON_YELLOW 2

   call get_cur_coord
   mov r8, 0        ; curses requires the "opts" parameter for future features
                    ; that aren't currently implemented. so we just set it to 0.
   mov rcx, BLACK_ON_YELLOW ; or whatever you named the color pair index using
                    ; init_color
   mov rdx, 0       ; the string attribute; 0 for normal, and 200000h for bold
   mov rsi,42       ; the length of the error message you printed.
   mov rdi, [hWindow]      ; the window your string was printed on.
   call wchgat

;  call draw_child_window3
   mov rdx,50    ;  X
   mov rsi,11    ;  Y
;   mov rdi,[hChildWindow3]
   mov rdi,[hWindow]
   call wmove
;*****************

The use-case for writing an error message would be:
1. Save the cursor position using the get_cur_coord macro.
2. Write your error message using the waddstr procedure.
3. Restore cursor position using the wmove procedure.
4. Change attributes from current position to n-bytes, where n is the length of your error message, using the wchgat procedure.

You should try to implement this as a procedure.

also never got this to work.
trying to run NASM from a HD not containing the OS.
Code: [Select]
jack@jack-myheadache ~ $ sudo mount -o remount,exec /media/jack/nasm/nasmfld
[sudo] password for jack:
mount: can't find /media/jack/nasm/nasmfld in /etc/fstab or /etc/mtab
jack@jack-myheadache ~ $

Maybe you can ask for help on that at the Linux Mint community forums. They might be able to walk you through editing /etc/fstab to enable exec on your partition. I'd rather not try and talk you through it when i don't have a Linux Mint (or a 64-bit Linux) at my disposal for testing locally.

In MASM32 we have macro called "ATODW".
It converts a decimal string into a dw value.
CkBal db  '     4321',0
mathhold dd 0
I thought this was what "atoi" did....
more about this problem below.
Code: [Select]
; the user keys in "aa" incorrectly

hChildWindow   dq 0
msg                   dw 0   ; converted user input ??
szUserInput       db '  ',0

   mov rdx,2
   mov rsi,szUserInput
   mov rdi,[hChildWindow]
   call wgetnstr      ; reads 2 characters good or bad

;;   convert string to integer
   mov rdi,szUserInput
   call atoi   ; result in rax

   mov [msg],ax     ; preserve keyed in value ??
   cmp byte[msg+1],016h  ; This does not work!!!!!!!!!
                         ; value should not be > 22 decimal
    jg .err1
    jmp .out1               ; good input

; never gets here.............
.err1:
   call draw_child_window3
   mov rdx,50    ;  X
   mov rsi,11    ;  Y
   mov rdi,[hChildWindow3]
   call wmove
;msg6       db 'value keyed in is invalid - reenter ',0
   mov rsi,msg6
   mov rdi,[hChildWindow3]
   call waddstr

;;   The command wrote a string in the window buffer,
;;   now we need to display the buffer on the screen.
   mov rdi,[hChildWindow3]
   call wrefresh

The atoi procedure isn't exactly like ATODW from MASM32 package. atoi will convert a string of characters that representing numbers into an integer. However, it stops it's conversion if it runs into anything else. In your "aa" example, atoi is returning 0 because it didn't get a value from the string. If you were to pass atoi the string "55x2", atoi would return 55 and ignore the rest. If you want to ensure the string entered contains only digits, you'll need to check each character from the szUserInput buffer to ensure they are all digits. Since you're working with just two characters, this shouldn't be too hard. You could even do it inline (no loop) like this:

Code: [Select]
   mov al, byte [szUserInput]
   cmp al, '0'
   jb .err1
   cmp al, '9'
   ja .err1

   mov al, byte [szUserInput+1]
   cmp al, '0'
   jb .err1
   cmp al, '9'
   ja .err1
   jmp .out1

.err1:
   ;; one of the characters wasn't a decimal digit,
   ;; do our error for invalid input then jump to end
   ;; of procedure.

.out1:
   ;; both characters read are decimal digits, convert
   ;; them to integers.
   mov rdi, szUserInput
   call atoi
Title: Re: beginner questions
Post by: jackjps on March 18, 2016, 06:43:10 PM
      3-18-2015
Just Info.
Much to my surprise and using input from the user, "szUserInput"
codes a letter as 061h.
The number 0 is coded as 030h. This is without using "atoi".
Puzzling....
Title: Re: beginner questions
Post by: Bryant Keller on March 18, 2016, 07:13:20 PM
Your computer doesn't understand concepts such as pictures, sounds, or even letters. All the computer understands are numbers. But this isn't good enough for us humans, we like pictures, sounds, and letters.. even more so, we like combinations of pictures (video), sounds (music), and letters (words). So internally, computers tend to represent these more abstract things that people like, as numbers. In this case, you're introduced to something known as ASCII code. ASCII code is how your computer is storing letters based on the context in which they are used. Here is a full list of the ASCII code table:

Code: [Select]
Char  Dec  Oct  Hex | Char  Dec  Oct  Hex | Char  Dec  Oct  Hex | Char Dec  Oct   Hex
-------------------------------------------------------------------------------------
(nul)   0 0000 0x00 | (sp)   32 0040 0x20 | @      64 0100 0x40 | `      96 0140 0x60
(soh)   1 0001 0x01 | !      33 0041 0x21 | A      65 0101 0x41 | a      97 0141 0x61
(stx)   2 0002 0x02 | "      34 0042 0x22 | B      66 0102 0x42 | b      98 0142 0x62
(etx)   3 0003 0x03 | #      35 0043 0x23 | C      67 0103 0x43 | c      99 0143 0x63
(eot)   4 0004 0x04 | $      36 0044 0x24 | D      68 0104 0x44 | d     100 0144 0x64
(enq)   5 0005 0x05 | %      37 0045 0x25 | E      69 0105 0x45 | e     101 0145 0x65
(ack)   6 0006 0x06 | &      38 0046 0x26 | F      70 0106 0x46 | f     102 0146 0x66
(bel)   7 0007 0x07 | '      39 0047 0x27 | G      71 0107 0x47 | g     103 0147 0x67
(bs)    8 0010 0x08 | (      40 0050 0x28 | H      72 0110 0x48 | h     104 0150 0x68
(ht)    9 0011 0x09 | )      41 0051 0x29 | I      73 0111 0x49 | i     105 0151 0x69
(nl)   10 0012 0x0a | *      42 0052 0x2a | J      74 0112 0x4a | j     106 0152 0x6a
(vt)   11 0013 0x0b | +      43 0053 0x2b | K      75 0113 0x4b | k     107 0153 0x6b
(np)   12 0014 0x0c | ,      44 0054 0x2c | L      76 0114 0x4c | l     108 0154 0x6c
(cr)   13 0015 0x0d | -      45 0055 0x2d | M      77 0115 0x4d | m     109 0155 0x6d
(so)   14 0016 0x0e | .      46 0056 0x2e | N      78 0116 0x4e | n     110 0156 0x6e
(si)   15 0017 0x0f | /      47 0057 0x2f | O      79 0117 0x4f | o     111 0157 0x6f
(dle)  16 0020 0x10 | 0      48 0060 0x30 | P      80 0120 0x50 | p     112 0160 0x70
(dc1)  17 0021 0x11 | 1      49 0061 0x31 | Q      81 0121 0x51 | q     113 0161 0x71
(dc2)  18 0022 0x12 | 2      50 0062 0x32 | R      82 0122 0x52 | r     114 0162 0x72
(dc3)  19 0023 0x13 | 3      51 0063 0x33 | S      83 0123 0x53 | s     115 0163 0x73
(dc4)  20 0024 0x14 | 4      52 0064 0x34 | T      84 0124 0x54 | t     116 0164 0x74
(nak)  21 0025 0x15 | 5      53 0065 0x35 | U      85 0125 0x55 | u     117 0165 0x75
(syn)  22 0026 0x16 | 6      54 0066 0x36 | V      86 0126 0x56 | v     118 0166 0x76
(etb)  23 0027 0x17 | 7      55 0067 0x37 | W      87 0127 0x57 | w     119 0167 0x77
(can)  24 0030 0x18 | 8      56 0070 0x38 | X      88 0130 0x58 | x     120 0170 0x78
(em)   25 0031 0x19 | 9      57 0071 0x39 | Y      89 0131 0x59 | y     121 0171 0x79
(sub)  26 0032 0x1a | :      58 0072 0x3a | Z      90 0132 0x5a | z     122 0172 0x7a
(esc)  27 0033 0x1b | ;      59 0073 0x3b | [      91 0133 0x5b | {     123 0173 0x7b
(fs)   28 0034 0x1c | <      60 0074 0x3c | \      92 0134 0x5c | |     124 0174 0x7c
(gs)   29 0035 0x1d | =      61 0075 0x3d | ]      93 0135 0x5d | }     125 0175 0x7d
(rs)   30 0036 0x1e | >      62 0076 0x3e | ^      94 0136 0x5e | ~     126 0176 0x7e
(us)   31 0037 0x1f | ?      63 0077 0x3f | _      95 0137 0x5f | (del) 127 0177 0x7f

As you can see, it expects that the hex value 0x61 is translated as the letter 'a'. This ASCII standard allows for all applications that use letters as data, to store them in the same way.
Title: Re: beginner questions
Post by: jackjps on March 22, 2016, 10:40:17 AM
Hi Bryant,
                        3-22-2016
This is the response I got so far from the linux mint forum.
I have no idea what they are talking about.
I don't know if I already have Dolphin on my Linux or how to get it.

The link below explains how to use chmod to set permissions for an additional drive. This particular article references an external drive but the process is basically the same for an additional internal drive.

http://stackoverflow.com/questions/2058 ... ing-access

Alternatively you can install the Dolphin file manager GUI, open a command prompt with #sudo dolphin, enter your password, then when the GUI opens, right click on the drive, click Permissions and select the option to share with all users.
Top
User avataradministrollaattori
Level 9
Level 9
Re: separate drive for linux mint
PostMon Mar 21, 2016 4:11 pm

What tells commands
CODE: SELECT ALL
lsblk
cat /etc/fstab
Title: Re: beginner questions
Post by: Bryant Keller on March 24, 2016, 03:52:38 AM
I've personally never heard of Dolphin, but it appears to be a KDE file manager (https://community.linuxmint.com/software/view/dolphin). Basically, they are telling you to open the Dolphin file manager with administrative privileges using sudo dolphin, right click on the drive and click the "Permissions" tab to select the option to "share with all users". Personally, I use FXCE desktop with Thunar file manager. The process is similar with it; run Thunar with administrative privileges using sudo Thunar (yes, that's capital T). This will give you a window that has a yellows bar saying "Warning, you are using the root account, you may harm your system". Use that file manager to navigate to the directory your files are at and Right Click in an empty space of the folder and click "Properties" at the bottom of the context menu. A dialog will appear and click "Permissions" tab. Under the "Permissions" tab, change the "Others:" option to "Read & Write", close the dialog, then close Thunar file manager. Hopefully, that should fix it.
Title: Re: beginner questions
Post by: jackjps on March 24, 2016, 08:33:25 AM
Code: [Select]
Hi Bryant,
1. Got it to work using your stuff. I think.
    Now if Linux Mint gets corrupted I'll be able to reinstall it
   without losing the goodies in NASM.
   I compiled the demo64 program on the HD separate from Linux.
  That worked fine. When I tried to execute the program I got 
  the following:

jack@jack-myheadache /media/jack/NASM/nasmfld $ ./demo64
bash: ./demo64: Permission denied
jack@jack-myheadache /media/jack/NASM/nasmfld $

   Is it possible that I was not in administrator mode??
   Don't know how to get there in Linux..... 

2.  Trying to understand your explanation of adding colors to the screen.
     When I do man wchgat all I get is a screen showing data for "attr"?
     
3.  In Masm32 I avoided Macros like the plague. I like to see, in my code,
     the full code for anything that needs repeated. I would write it once
     and branch to and return from it as many times as needed. This way I
     don't have to go digging for what the macro does and it's parameters.
     In NASM I have trouble knowing what is a marco and what are it's
     parameters and where to find data on the macro.
     This is my problem right now with "get_cur_coord".   
     Thanks for your help.
Title: Re: beginner questions
Post by: Bryant Keller on March 27, 2016, 12:56:43 AM
Hi Bryant,
1. Got it to work using your stuff. I think.
    Now if Linux Mint gets corrupted I'll be able to reinstall it
   without losing the goodies in NASM.
   I compiled the demo64 program on the HD separate from Linux.
  That worked fine. When I tried to execute the program I got 
  the following:

jack@jack-myheadache /media/jack/NASM/nasmfld $ ./demo64
bash: ./demo64: Permission denied
jack@jack-myheadache /media/jack/NASM/nasmfld $

   Is it possible that I was not in administrator mode??
   Don't know how to get there in Linux..... 

Maybe you should try this command:

Code: [Select]
$ sudo chown -R jack /media/jack
That should recursively scan through all files and directories in /media/jack and make the file/directories' owner jack.

2.  Trying to understand your explanation of adding colors to the screen.
     When I do man wchgat all I get is a screen showing data for "attr"?

Documentation for that routine is in the same manual entry for all attribute changing routines (including attron, attroff, etc.) Scrolling down a bit, you'll see the Synopsis for wchgat is:

Quote from: man wchgat
       int wchgat(WINDOW *win, int n, attr_t attr,
             short color, const void *opts)

And the explanation is bit further down:

Quote from: man wchgat
       The routine chgat changes the attributes of a given number  of  charac?
       ters  starting  at  the current cursor location of stdscr.  It does not
       update the cursor and does not perform wrapping.  A character count  of
       -1  or  greater  than  the  remaining  window width means to change at?
       tributes all the way to the end of the current line. The wchgat  func?
       tion  generalizes this to any window; the mvwchgat function does a cur?
       sor move before acting.  In these functions, the color  argument  is  a
       color-pair  index  (as  in  the  first  argument of init_pair, see col?
       or
(3NCURSES)).  The opts argument is not presently  used,  but  is  re?
       served for the future (leave it NULL).

The striked out section should be ignored. The features of NCURSES documented with the 'mv' prefix are implemented as C macros, so in assembly you have to call the wmove procedure separately.

3.  In Masm32 I avoided Macros like the plague. I like to see, in my code,
     the full code for anything that needs repeated. I would write it once
     and branch to and return from it as many times as needed. This way I
     don't have to go digging for what the macro does and it's parameters.
     In NASM I have trouble knowing what is a marco and what are it's
     parameters and where to find data on the macro.
     This is my problem right now with "get_cur_coord".   
     Thanks for your help.

There is no need to "dig" for what the macro does and it's parameters, I gave you the macro, I told you the parameters.
Do us both a favor and re-read the reply I referred you to. For clarity, I'll repost the link:

http://forum.nasm.us/index.php?topic=2204.msg9799#msg9799 (http://forum.nasm.us/index.php?topic=2204.msg9799#msg9799)

I'll take partial blame for this, maybe it's my coding style that is throwing you off. I'll give you a quick introduction into the process I use to create procedures and/or macros. From this point on, I'll refer to procedures and macros as processes, not to be confused with tasks which are sometimes also called processes.. In any event, just note that when I use the word process in the following, I mean any type of procedure, function, or macro.

Step 1. - Interface Specification.

An interface specification is a contract you make with other developers (or yourself) about how the code you plan to write will be used. In general, the interface specification needs to define the name of the process, the inputs that are consumed by the process, and the outputs that are produced as a result of the process' execution. There are many styles of writing interface specifications, but the one I use is the single-line form:

Code: [Select]
;; process_name : inputs -> outputs
When you see this type of interface specification, it reads as "process_name consumes inputs and produces outputs". So, for example, when I wrote get_cur_coord macro, I began by writing the comment line:

Code: (get_cur_coord) [Select]
;; get_cur_coord : window_handle -> { x y }
Like before, this should read as "get_cur_coord consumes window_handle and produces x and y". This means that the macro takes a single argument (the window handle) and returns to you the values of X and Y.

Step 2. - Process Description.

This is a very important step! Many programmers will skip that first step assuming that the reader of the source code can infer from context the inputs and outputs, but no programmers with any real experience will leave out the process description in software they expect people to regularly use. The process description extends on the interface specification by giving a general description of what the process expects to accomplish. This is usually a paragraph that appears just below the interface specification. People who leave out the interface specification are usually taught to put this description within the code block before any actual code (you'll see people do that a lot in Visual Basic). I use my interface specifications, so I put it after them. In our get_cur_coord example, it reads;

Code: (get_cur_coord) [Select]
;; Obtains the current X and Y coordinates from a window handle
;; and returns the current X coordinate in rax and the current
;; Y coordinate in rbx.

This process description tells you that this process will obtain an X and Y coordinate from a window handle, then goes on to further explain that the X value will be located in the RAX register and the Y value in the RBX. From this description, you should be able to infer how to use the process. If we write the code:

Code: [Select]
get_cur_coord [hWindow]
After this process, the value of RAX is the X coordinate and the value of RBX is the Y coordinate.

Step 3. - Examples.

I think this is where I messed up in my code, I left this part out. When i post code on the forum, I tend to remove this comment to reduce the overall code size. I have a tendency to be verbose, or long-winded to use a local term, and I regularly hit the post length limit. So I reduce code by stripping out stuff i think people aren't going to care much about; this always includes the example section. However, it's an important part of my development process and I think I should at least explain it.

At this point in the design process, I'll take the information I've accumulated so far (the interface specification and process description) and formalize the expectations of the process. The reason I skipped this in the get_cur_coord example is simply because I was too lazy to write one. This is a bad excuse, but writing examples for processes which have "artifacts" or have some form of internal state are difficult to write. A good example of this difficulty would be a process for a random number generator. It's hard to describe a behavioral expectation for something that has an unpredictable behavior. The general layout of an example section (at least in my code) will usually be a list of uses with an '=>'  followed by the expected result. If I was to give this a try with the get_cur_coord macro, I'd probably implement it as:

Code: [Select]
;; given
;; wmove (hWindow, 0, 0); get_cur_coord [hWindow] => { RAX: 0, RBX 0 },
;; wmove (hWindow, 5, 4); get_cur_coord [hwindow] => { RAX: 4, RBX 5 }, and
;; wmove (hWindow, LINES, COLS); get_curr_coord [hWindow] => { RAX: COLS, RBX: LINES }.

This comment should assume nothing about the calling conventions used, so in this example you can see I'm referencing a call to wmove as though it was a C routine. The idea here is that we imply enough information about the use that we can formalize some form of test cases.

Step 4. - Unit Testing.

This is another section which I didn't implement in my example, and you'll rarely ever see in any code you'll download. The purpose of the unit testing code is to implement a series of processes which do exactly what your examples earlier did. It may seem odd at first that we are developing test cases before we develop the actual code, but there is valid reasoning here. The unit tests should be an un-biased VALIDATION that our implementation is properly working. There is an overwhelming urge to use our implementation to design our test cases, though this would be considerably easier, it would increase the odds that a flawed implementation detail could be overlooked.

Our expected unit test would look something like this:

Code: [Select]
get_cur_coord_ut:
   STACK_ALIGN


;; given wmove (hWindow, 0, 0); get_cur_coord [hWindow]

   mov rdx, 0
   mov rsi, 0
   mov rdi, [hWindow]
   call wmove

   get_cur_coord [hWindow]

;; expect { RAX: 0, RBX 0 }

   cmp rax, 0
   jne .FAIL
   cmp rbx, 0
   jne .FAIL

;; given wmove (hWindow, 5, 4); get_cur_coord [hwindow]

   mov rdx, 4
   mov rsi, 5
   mov rdi, [hWindow]
   call wmove

   get_cur_coord [hWindow]

;; expect { RAX: 4, RBX 5 }

   cmp rax, 4
   jne .FAIL
   cmp rbx, 5
   jne .FAIL

;; given wmove (hWindow, LINES, COLS); get_curr_coord [hWindow]

   mov rdx, [COLS]
   mov rsi, [LINES]
   mov rdi, [hWindow]
   call wmove

   get_cur_coord [hWindow]

;; expect { RAX: COLS, RBX: LINES }

   cmp rax, [COLS]
   jne .FAIL
   cmp rbx, [LINES]
   jne .FAIL

.SUCCESS:
   mov rax, TRUE
   jmp .DONE

.FAIL:
   mov rax, FALSE

.DONE:
   STACK_RESTORE
   ret

At this point, when we implement the process, we now have a method of validating whether the implementation satisfies our initial expectations or not.

Step 5. - Process Implementation.

Once we have designed all this support information, we can design the process implementation itself. In my earlier post, i gave you the interface specification, the description, and the process implementation. In this case, I looked up the implementation details of NCURSES' window structure and saw that the current Y coordinate is the first 16-bit element and the current X coordinate is the second 16-bit element of the data structure. That means, our use case for this process is to consume (as input) a window handle and produce (as output) the first element of that structure in BX and the second element of that structure in AX. Because RAX and RBX may already contain values, we need to clear the registers before retrieving the elements. So, to summarize:

Use-Case:
1. Obtain reference to our window handle.
2. Clear RAX and RBX registers.
3. Assign first 16-bit value in structure to BX.
4. Assign second 16-bit value in structure to AX.

To do this, we'll need to use a register for dereferencing the window handle and that register should probably be saved and restored in case it's currently being used. This changes our use-case to:

Use-Case:
1. Save RSI register.
2. Obtain reference to our window handle and put it in RSI.
3. Clear RAX and RBX registers.
4. Assign first 16-bit value in structure to BX.
5. Assign second 16-bit value in structure to AX.
6. Restore RSI register.

This use-case analysis finally lead me to my implementation which was a transformation of the steps to instructions:

Code: (get_cur_coord) [Select]
%macro get_cur_coord 1
push rsi
mov rsi, %1
xor rax, rax
xor rbx, rbx
mov ax, [rsi + 2]
mov bx, [rsi]
pop rsi
%endmacro

This could also have been implemented using a procedure (note: the calling convention takes parameters in RDI so we'll just use that instead of RSI).

Code: [Select]
;; get_cur_coord_proc : window_handle -> { x y }.
;; Obtains the current coordinates from a window handle in RDI
;; and returns the current x-coordinate in RAX and the current
;; y-coordinate in RBX.
;; given
;; wmove (hWindow, 0, 0); get_cur_coord_proc (hWindow) => { RAX: 0, RBX 0 },
;; wmove (hWindow, 5, 4); get_cur_coord_proc (hwindow) => { RAX: 4, RBX 5 }, and
;; wmove (hWindow, LINES, COLS); get_curr_coord_proc (hWindow) => { RAX: COLS, RBX: LINES }.
get_cur_coord_proc:
   STACK_ALIGN
   xor rax, rax
   xor rbx, rbx
   mov ax, [rdi + 2] ; second element (x-coord)
   mov bx, [rdi] ; first element (y-coord)
   STACK_RESTORE
   ret

This would, of course, require our unit test code to be changed.

In any event, I hope this clears up any confusion as to my coding style when trying to read examples I provide you. You're not the first to mention difficulty in understanding my code. It helps to point out that most of my "design" techniques come from functional programming whereas most of my implementation practices come from assembly language and a few high level structured languages. I tend to assume that people can infer the meaning of my code from context, but that is rarely the case.



As a reminder, be sure to review the previous reply I referred to:

http://forum.nasm.us/index.php?topic=2204.msg9799#msg9799 (http://forum.nasm.us/index.php?topic=2204.msg9799#msg9799)



Regards,
Bryant Keller
Title: Re: beginner questions
Post by: jackjps on March 27, 2016, 09:42:00 AM
Code: [Select]
Hi Bryant,
1.   Still trying to get nasm to work on the separate HD.

jack@jack-myheadache /media/jack/NASM/nasmfld $ sudo chown -R jack /media/jack
[sudo] password for jack:
jack@jack-myheadache /media/jack/NASM/nasmfld $ nasm -f elf64 demo64.asm -o demo64.o
jack@jack-myheadache /media/jack/NASM/nasmfld $ gcc -o demo64 demo64.o -lcurses
jack@jack-myheadache /media/jack/NASM/nasmfld $ ./demo64
bash: ./demo64: Permission denied
jack@jack-myheadache /media/jack/NASM/nasmfld $

2. understanding the parameters of wchgat
    mov r8,0 
    mov rcx,COLOR_PAIR(BLACK_ON_WHITE)
    mov rdx,0
    mov rsi,len1
    mov rdi,[hWindow] 
    call wchgat

   Is my understanding of wchgat correct:
   mov r8,0 =s   const void *opts
   mov rcx,COLOR_PAIR(BLACK_ON_WHITE) =s   short color
   mov rdx,0 =s   attr_t_attr
   mov rsi,len1 =s   int n 
   mov rdi,[hWindow] =s   Window *win

    int wchgat(WINDOW *win, int n, attr_t attr,
             short color, const void *opts)
   
    Let me try to explain what I need for the demo64 program.
    In Masm32 or Goasm you could vary colors by 250,000 ways.
    I see in Nasm only color pairs that are very limited.
    For instance the demo64 program screen has a faded out blue
    a faded yellow rectangle. If the above wchgat is the way to solve
    this then I need to understand how to fill out the instruction.
    Where can I read more about this?

3. Where can I read about changing Fonts?
    Is this part of the "ATTR"?
Title: Re: beginner questions
Post by: Bryant Keller on March 28, 2016, 01:32:45 AM
1.   Still trying to get nasm to work on the separate HD.
Code: [Select]
jack@jack-myheadache /media/jack/NASM/nasmfld $ sudo chown -R jack /media/jack
[sudo] password for jack:
jack@jack-myheadache /media/jack/NASM/nasmfld $ nasm -f elf64 demo64.asm -o demo64.o
jack@jack-myheadache /media/jack/NASM/nasmfld $ gcc -o demo64 demo64.o -lcurses
jack@jack-myheadache /media/jack/NASM/nasmfld $ ./demo64
bash: ./demo64: Permission denied
jack@jack-myheadache /media/jack/NASM/nasmfld $

Try the command ls -al /media/jack/NASM/nasmfld and post the results here. I want to see what file attributes are being set.

2. understanding the parameters of wchgat
Code: [Select]
    mov r8,0 
    mov rcx,COLOR_PAIR(BLACK_ON_WHITE)
    mov rdx,0
    mov rsi,len1
    mov rdi,[hWindow] 
    call wchgat

   Is my understanding of wchgat correct:
Code: [Select]
   mov r8,0 =s   const void *opts
   mov rcx,COLOR_PAIR(BLACK_ON_WHITE) =s   short color
   mov rdx,0 =s   attr_t_attr
   mov rsi,len1 =s   int n 
   mov rdi,[hWindow] =s   Window *win

Code: [Select]
    int wchgat(WINDOW *win, int n, attr_t attr,
             short color, const void *opts)

Yep, that's exactly what's going on. Remembering of course that you need to put the cursor at the position where the text is at using the wmove procedure. This is kind of awkward because you are writing a string (probably with waddstr), then moving the cursor back to the start of the string and applying the formatting. It's a lot of work for colored text in the console, but it's a necessary evil.

    Let me try to explain what I need for the demo64 program.
    In Masm32 or Goasm you could vary colors by 250,000 ways.
    I see in Nasm only color pairs that are very limited.
    For instance the demo64 program screen has a faded out blue
    a faded yellow rectangle. If the above wchgat is the way to solve
    this then I need to understand how to fill out the instruction.
    Where can I read more about this?

Your issue here isn't really with NASM. You were able to do so much with Masm32 and GoASM because you were writing code for Windows and you had direct (or possibly abstracted through emulation) access to the hardware's display. I'm sure Frank could show you plenty of examples of people doing the same thing NASM in DOS/Windows consoles. The problem, if you want to call it that, is that Linux is not Windows. Linux Mint is providing you with a Terminal emulator (https://en.wikipedia.org/wiki/Terminal_emulator) which means you are limited to using the colors that are supported by the terminal environment. The ANSI color support (in most terminals) is limited to only a few colors:

Intensity     0               1               2               3               4               5               6               7               









NormalBlackRedGreenYellow *BlueMagentaCyanWhite
BrightBlackRedGreenYellowBlueMagentaCyanWhite









* On some terminals Normal Yellow will appear as Orange or Brown.

If you want more colorful applications, then I suggest you start reading up on GUI toolkits like Xlib or Gtk.

3. Where can I read about changing Fonts?
    Is this part of the "ATTR"?

Short answer, you can't. Slightly longer answer, CURSES is implemented in such a way that it just uses character sets and escape sequences to display information and none of the escape sequences support changing fonts.



Change of pace. I don't want this reply to be just doom and gloom. It kinds sucks that the things you're wanting to do can't be done the same way it can be done on Windows. But there is a silver lining here (somewhat). You're not the first person to have this problem. Usually, when many people deal with the same problems, eventually one of them fixes it. What follows are a list of console related projects that allow you to do more advanced stuff.

The Linux Framebuffer
One you may be interested in is called the Linux Framebuffer (https://www.kernel.org/doc/Documentation/fb/framebuffer.txt). I've personally never done framebuffer development, but what I gather is you just open the framebuffer's device and map it to memory, modify it and write it back to the device. Again, I've not actually done this so I don't know much about it, but kernel.org (the place where Linux itself is made) has a vague text on it:

https://www.kernel.org/doc/Documentation/fb/framebuffer.txt (https://www.kernel.org/doc/Documentation/fb/framebuffer.txt)

That should allow you to do pixel related graphics in the console, and in theory you could draw up your own fonts and render them too. As for actually implementing code for FrameBuffer, maybe Frank has done some of this, or possibly someone else. No clue myself though, you're kinda on your own there.

The Linux SuperVGA Graphics Library
For people coming from a DOS/Windows background, the SuperVGA Graphics Library (http://www.svgalib.org/) should look really familiar. This library is a graphics wrapper that allows you to develop graphical applications in the Linux console in almost exactly the same way you might have done in TurboC on DOS (that's what the source code reminds me of anyway). Not only does this library give you access to pixel graphics, but also natively supports bitmap fonts. According to the information on the SVGALib website, there is a "sister library" called vgagl that'll extend support to scalable fonts as well.

The SVGALib site has several tutorials and quite a few programs that you can reference to see what's possible. This is used a good bit for console based game development.



Regards,
Bryant Keller
Title: Re: beginner questions
Post by: jackjps on March 28, 2016, 09:54:19 AM
Code: [Select]
Hi Bryant,
As per your request:

#1
jack@jack-myheadache ~ $ sudo ls -al /media/jack/NASM/nasmfld
[sudo] password for jack:
total 1507
drwx------ 1 jack jack    4096 Mar 27 05:37 .
drwx------ 1 jack jack    4096 Mar 24 04:28 ..
-rw------- 1 jack jack    5408 Mar  6 16:42 Bryantscd
-rw------- 1 jack jack    4747 Mar  1 15:30 demo264.asm
-rw------- 1 jack jack   17354 Mar 27 05:37 demo64
-rw------- 1 jack jack   20093 Mar 26 16:53 demo64.asm
-rw------- 1 jack jack   12224 Mar 27 05:37 demo64.o
-rw------- 1 jack jack      42 Feb 29 07:32 demo64.sh
-rw------- 1 jack jack     942 Feb 19 16:38 hello
-rw------- 1 jack jack     457 Feb 19 16:37 hello.asm
-rw------- 1 jack jack     848 Feb 19 16:38 hello.o
-rw------- 1 jack jack    7568 Mar  7 08:33 lcurses
-rw------- 1 jack jack   12224 Mar 27 04:56 -lcurses
-rw------- 1 jack jack     592 Mar  7 08:21 LNInstructions.txt
drwx------ 1 jack jack   24576 Mar  8 11:40 nasm-2.11.08
-rw------- 1 jack jack 1398894 Feb 14 09:51 nasm-2.11.08.zip
-rw------- 1 jack jack     142 Mar 12 12:18 testnano.txt
-rw------- 1 jack jack    7493 Feb 22 16:10 tprt64c.asm
jack@jack-myheadache ~ $

#2             3-28-2016
HI Bryant,

hChildWindow   dq 0
szUserInput    db 0, 0, 0  ; don't understand this
;szUserInput    db '  ',0   ; why not this way????
I have the same problem below no matter which way I
define szUserInput.

;;  create 1st child window
   mov rcx,50    ; x value
   mov rdx,10    ; y value
   mov rsi,3     ; 3 columns for 2 digits
   mov rdi,1     ; 1 line for 1 row of digits
   call newwin
   mov [hChildWindow],rax

.g1:
   mov rdx,2
   mov rsi,szUserInput
   mov rdi,[hChildWindow]
   call wgetnstr      ; reads 2 characters good or bad
 
Every time the user keys in a wrong digit I return to
.g1 and get new digits from the user. Whatever wrong
digits/characters the user keys in I get the same error
message on the screen. This is wrong. I am doing something
wrong!
Also, I don't understand the way szUserInput is defined?

oh my - #3 is going to keep me busy for months....




Title: Re: beginner questions
Post by: Bryant Keller on March 30, 2016, 03:51:40 AM
Code: [Select]
jack@jack-myheadache ~ $ sudo ls -al /media/jack/NASM/nasmfld
[sudo] password for jack:
total 1507
drwx------ 1 jack jack    4096 Mar 27 05:37 .
drwx------ 1 jack jack    4096 Mar 24 04:28 ..
-rw------- 1 jack jack    5408 Mar  6 16:42 Bryantscd
-rw------- 1 jack jack    4747 Mar  1 15:30 demo264.asm
-rw------- 1 jack jack   17354 Mar 27 05:37 demo64
-rw------- 1 jack jack   20093 Mar 26 16:53 demo64.asm
-rw------- 1 jack jack   12224 Mar 27 05:37 demo64.o
-rw------- 1 jack jack      42 Feb 29 07:32 demo64.sh
-rw------- 1 jack jack     942 Feb 19 16:38 hello
-rw------- 1 jack jack     457 Feb 19 16:37 hello.asm
-rw------- 1 jack jack     848 Feb 19 16:38 hello.o
-rw------- 1 jack jack    7568 Mar  7 08:33 lcurses
-rw------- 1 jack jack   12224 Mar 27 04:56 -lcurses
-rw------- 1 jack jack     592 Mar  7 08:21 LNInstructions.txt
drwx------ 1 jack jack   24576 Mar  8 11:40 nasm-2.11.08
-rw------- 1 jack jack 1398894 Feb 14 09:51 nasm-2.11.08.zip
-rw------- 1 jack jack     142 Mar 12 12:18 testnano.txt
-rw------- 1 jack jack    7493 Feb 22 16:10 tprt64c.asm
jack@jack-myheadache ~ $

Okay! Now we see what the problem is. The file 'demo64' is a program but it's not marked as executable. Unlike Windows, Linux doesn't use the file extension to determine how a file should be used. In your listing, we can tell because there is no 'x' in the -rw------- part before the file. Try the command chmod +x /media/jack/NASM/nasmfld/demo64. The "chmod" program changes the file mode bits on a given file or directory. The "+x" portion means "make this file executable". At this point, you don't need that pesky sudo anymore because we can see that the file and group settings tell us you really do have permission to access this file.  ;)

After you use the chmod command, try to execute the program, if you get the same error, do ls -al /media/jack/NASM/nasmfld and post the results here again.

#2             3-28-2016
HI Bryant,

hChildWindow   dq 0
szUserInput    db 0, 0, 0  ; don't understand this
;szUserInput    db '  ',0   ; why not this way????
I have the same problem below no matter which way I
define szUserInput.

If you look at the ASCII code table, you'll note that 0 is a (nul) character. This character is used as an end of string character and users aren't likely to enter it as user input. A space, however, can be easily entered by the user. In the grand scheme of things, it's not a big deal, but zero'ing out the memory lets you know that it's properly initialized. :)


;;  create 1st child window
   mov rcx,50    ; x value
   mov rdx,10    ; y value
   mov rsi,3     ; 3 columns for 2 digits
   mov rdi,1     ; 1 line for 1 row of digits
   call newwin
   mov [hChildWindow],rax

.g1:
   mov rdx,2
   mov rsi,szUserInput
   mov rdi,[hChildWindow]
   call wgetnstr      ; reads 2 characters good or bad
 
Every time the user keys in a wrong digit I return to
.g1 and get new digits from the user. Whatever wrong
digits/characters the user keys in I get the same error
message on the screen. This is wrong. I am doing something
wrong!
Also, I don't understand the way szUserInput is defined?

oh my - #3 is going to keep me busy for months....
[/code]

When you detect that the input isn't a valid digit, you'll need to set the values back to the initialized versions and clear the screen before jumping back to the .g1 label.

Code: [Select]
.g1:
   mov rdx,2
   mov rsi,szUserInput
   mov rdi,[hChildWindow]
   call wgetnstr      ; reads 2 characters good or bad

   mov al, byte [szUserInput]
   cmp al, '0'
   jb .err1
   cmp al, '9'
   ja .err1

   mov al, byte [szUserInput+1]
   cmp al, '0'
   jb .err1
   cmp al, '9'
   ja .err1
   jmp .out1

.err1:
   ;; do our error for invalid input.
   ;;
   ;; ...
   ;;

   ;; Okay, at this point you've done whatever invalid input message
   ;; you wanted to display to the user, but we now need to get the new
   ;; user input...

   ;; First we reinitialize the string
   mov byte [szUserInput], 0
   mov byte [szUserInput + 1], 0

   ;; Now we need to clear that window.
extern wclear ; add this to the top section where the other extern's are at.
   mov rdi, [hChildWindow]
   call wclear

   ;; Then we should jump back and let the user try entering the code again.
   jmp .g1

.out1:
   ;; both characters read are decimal digits, convert
   ;; them to integers.
   mov rdi, szUserInput
   call atoi
Title: Re: beginner questions
Post by: Frank Kotler on March 30, 2016, 06:15:53 AM
A simple tutorial on those mysterious file permission letters:

https://support.rackspace.com/how-to/checking-linux-file-permissions-with-ls/

I'm puzzled how this could happen. Nasm doesn't know about OS file permissions. We can create a Linux executable without the assistance of a linker, but we've gotta do "chmod +x myfile" to be able to run it. But ld should create "demo64" with executable permission set without further action. If this happens with other files you write using Nasm and ld, you'll want to figure out why. It's an ld problem, not a Nasm problem.

Best,
Frank

Title: Re: beginner questions
Post by: jackjps on March 30, 2016, 11:46:54 AM
Code: [Select]
Hi Bryant,
Perhaps I have keyed your instructions incorrectly?

jack@jack-myheadache /media/jack/NASM/nasmfld $ sudo chmod +x /media/jack/NASM/nasmfld/demo64
[sudo] password for jack:
jack@jack-myheadache /media/jack/NASM/nasmfld $ sudo ls -al /media/jack/NASM/nasmfld
total 1507
drwx------ 1 jack jack    4096 Mar 27 05:37 .
drwx------ 1 jack jack    4096 Mar 24 04:28 ..
-rw------- 1 jack jack    5408 Mar  6 16:42 Bryantscd
-rw------- 1 jack jack    4747 Mar  1 15:30 demo264.asm
-rw------- 1 jack jack   17354 Mar 27 05:37 demo64
-rw------- 1 jack jack   20093 Mar 26 16:53 demo64.asm
-rw------- 1 jack jack   12224 Mar 27 05:37 demo64.o
-rw------- 1 jack jack      42 Feb 29 07:32 demo64.sh
-rw------- 1 jack jack     942 Feb 19 16:38 hello
-rw------- 1 jack jack     457 Feb 19 16:37 hello.asm
-rw------- 1 jack jack     848 Feb 19 16:38 hello.o
-rw------- 1 jack jack    7568 Mar  7 08:33 lcurses
-rw------- 1 jack jack   12224 Mar 27 04:56 -lcurses
-rw------- 1 jack jack     592 Mar  7 08:21 LNInstructions.txt
drwx------ 1 jack jack   24576 Mar  8 11:40 nasm-2.11.08
-rw------- 1 jack jack 1398894 Feb 14 09:51 nasm-2.11.08.zip
-rw------- 1 jack jack     142 Mar 12 12:18 testnano.txt
-rw------- 1 jack jack    7493 Feb 22 16:10 tprt64c.asm
jack@jack-myheadache /media/jack/NASM/nasmfld $

Title: Re: beginner questions
Post by: Bryant Keller on March 31, 2016, 02:28:27 AM
Okay, sounds like it could be an issue with your file system. Out of curiosity, try the mount -l command and post the output here.
Title: Re: beginner questions
Post by: jackjps on March 31, 2016, 05:56:09 AM
Code: [Select]
Hi Bryant,
Posted as per your previous request.

       mount directory          : mount known device here
       mount -t type dev dir    : ordinary mount command
Note that one does not really mount a device, one mounts
a filesystem (of the given type) found on the device.
One can also mount an already visible directory tree elsewhere:
       mount --bind olddir newdir
or move a subtree:
       mount --move olddir newdir
One can change the type of mount containing the directory dir:
       mount --make-shared dir
       mount --make-slave dir
       mount --make-private dir
       mount --make-unbindable dir
One can change the type of all the mounts in a mount subtree
containing the directory dir:
       mount --make-rshared dir
       mount --make-rslave dir
       mount --make-rprivate dir
       mount --make-runbindable dir
A device can be given by name, say /dev/hda1 or /dev/cdrom,
or by label, using  -L label  or by uuid, using  -U uuid .
Other options: [-nfFrsvw] [-o options] [-p passwdfd].
For many more details, say  man 8 mount .
jack@jack-myheadache /media/jack/NASM $
Title: Re: beginner questions
Post by: Bryant Keller on March 31, 2016, 06:35:10 AM
I wanted the output of mount -l. That's a lowercase L. This will list all mounted devices.

I have a file of bitmaps.
How can I include them in the demo64 program and use them?

You can't from the terminal. You'll need to use a GUI library like Gtk or Xlib.
Title: Re: beginner questions
Post by: jackjps on March 31, 2016, 06:47:55 AM
Code: [Select]
Hi Bryant,
Hope i got it right this time.....

proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
none on /sys/fs/cgroup type tmpfs (rw)
none on /sys/fs/fuse/connections type fusectl (rw)
none on /sys/kernel/debug type debugfs (rw)
none on /sys/kernel/security type securityfs (rw)
udev on /dev type devtmpfs (rw,mode=0755)
devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)
none on /run/shm type tmpfs (rw,nosuid,nodev)
none on /run/user type tmpfs (rw,noexec,nosuid,nodev,size=104857600,mode=0755)
none on /sys/fs/pstore type pstore (rw)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev)
systemd on /sys/fs/cgroup/systemd type cgroup (rw,noexec,nosuid,nodev,none,name=systemd)
gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,user=jack)
/dev/sda5 on /media/jack/NASM type fuseblk (rw,nosuid,nodev,allow_other,default_permissions,blksize=4096) [NASM]
/dev/sda7 on /media/jack/masm32 type fuseblk (rw,nosuid,nodev,allow_other,default_permissions,blksize=4096) [masm32]
jack@jack-myheadache /media/jack/NASM/nasmfld $

Title: Re: beginner questions
Post by: Bryant Keller on March 31, 2016, 07:07:01 AM
Okay, the problem is that the drive is NTFS. I've never used NTFS, but after searching around, I found a suggestion to try:

sudo umount /media/jack/NASM
sudo mount -t ntfs -o rw,auto,user,fmask=0022,dmask=0000,exec /dev/sda5 /media/jack/NASM

Title: Re: beginner questions
Post by: jackjps on March 31, 2016, 07:29:08 AM
Hi Bryant,
Yes, the hd is ntfs created by windows.
I put the NASM files on this drive.
I will try this again in case I was in the wrong place .

jack@jack-myheadache ~/nasmfld $ sudo umount /media/jack/nasm
[sudo] password for jack:
umount: /media/jack/nasm: not found
jack@jack-myheadache ~/nasmfld $
Title: Re: beginner questions
Post by: Bryant Keller on March 31, 2016, 07:34:09 AM
Linux is case-sensitive. nasm and NASM are two different things. Try again:

sudo umount /media/jack/NASM
sudo mount -t ntfs -o rw,auto,user,fmask=0022,dmask=0000,exec /dev/sda5 /media/jack/NASM

Title: Re: beginner questions
Post by: jackjps on March 31, 2016, 11:55:20 AM
Code: [Select]
#1
HI Bryant,
The HD is always open as it is a windows drive.

jack@jack-myheadache /media/jack/NASM $ sudo umount /media/jack/NASM
[sudo] password for jack:
umount: /media/jack/NASM: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
jack@jack-myheadache /media/jack/NASM $

I don't want to be a pest about this so I think another approach
might be in order. How about me just keeping Nasm up to date on
the HD? I can work on the SSD with Linux and Nasm. Should either
one fail I can restore Linux from the DVD and Nasm from the HD.
Not what I want but doable.

#2
Should I try to update Nasm to the latest version 2.12.01.
The only way I could find out what version of Nasm I am running
is by looking at the zip file I downloaded. It is v2.11.08

#3
                  4-2-2016
I am trying to get the year, month and day.
Not sure if any of this is right.

   extern time.h

   struc tm
     int tm.sec        ; seconds   ( 'INT" DO I NEED IT??)
     int tm.min        ; minutes
     int tm.hour       ; hours
     int tm.mday       ; day of the month
     int tm.mon        ; month
     int tm.year       ; year
     int tm.wday       ; day of the week
     int tm.yday       ; day in the year
     int tm.isdst      ; daylight saving time
   endstruc

   invoke GetLocalTime, addr tm  ; 449
    GetLocalTime is a Windows instruction
    Don't know what to replace it with?

   movzx eax,W[tm.year]            ; 450
   movzx ecx,W[tm.mon]            ; 451
   movzx ebx,W[tm.mday]          ; 452

jack@jack-myheadache ~/nasmfld $ nasm -f elf64 demo64.asm -o demo64.o
demo64.asm:449: error: parser: instruction expected
demo64.asm:450: error: comma, colon or end of line expected
demo64.asm:451: error: comma, colon or end of line expected
demo64.asm:452: error: comma, colon or end of line expected
jack@jack-myheadache ~/nasmfld $

 
Title: Re: beginner questions
Post by: Bryant Keller on April 03, 2016, 06:05:24 AM
#1
HI Bryant,
The HD is always open as it is a windows drive.

jack@jack-myheadache /media/jack/NASM $ sudo umount /media/jack/NASM
[sudo] password for jack:
umount: /media/jack/NASM: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
jack@jack-myheadache /media/jack/NASM $

I don't want to be a pest about this so I think another approach
might be in order. How about me just keeping Nasm up to date on
the HD? I can work on the SSD with Linux and Nasm. Should either
one fail I can restore Linux from the DVD and Nasm from the HD.
Not what I want but doable.

The reason the device is busy is because your currently in the directory. You have to run that command from somewhere other than on the drive.

#2
Should I try to update Nasm to the latest version 2.12.01.
The only way I could find out what version of Nasm I am running
is by looking at the zip file I downloaded. It is v2.11.08

You can tell your version by using the command nasm -v. The version I'm currently using is v2.11.07, so you're pretty up to date... I think I need to run updates. :D

#3
                  4-2-2016
I am trying to get the year, month and day.
Not sure if any of this is right.

   extern time.h

   struc tm
     int tm.sec        ; seconds   ( 'INT" DO I NEED IT??)
     int tm.min        ; minutes
     int tm.hour       ; hours
     int tm.mday       ; day of the month
     int tm.mon        ; month
     int tm.year       ; year
     int tm.wday       ; day of the week
     int tm.yday       ; day in the year
     int tm.isdst      ; daylight saving time
   endstruc

   invoke GetLocalTime, addr tm  ; 449
    GetLocalTime is a Windows instruction
    Don't know what to replace it with?

   movzx eax,W[tm.year]            ; 450
   movzx ecx,W[tm.mon]            ; 451
   movzx ebx,W[tm.mday]          ; 452

jack@jack-myheadache ~/nasmfld $ nasm -f elf64 demo64.asm -o demo64.o
demo64.asm:449: error: parser: instruction expected
demo64.asm:450: error: comma, colon or end of line expected
demo64.asm:451: error: comma, colon or end of line expected
demo64.asm:452: error: comma, colon or end of line expected
jack@jack-myheadache ~/nasmfld $

Nope, none of that is right.  :P It's okay though, we can fix it!  ;D

The extern directive is for specifying symbols (like the names of functions or variables) that are defined outside of our code. In your code, time.h is wrong because that's the name of a header file from the standard C library.

The structure portion is wrong too. The int's you are seeing are not interrupt instructions. In C they have a type called int which represents integers.

Invoke is not an instruction, it's a macro. Microsoft's MASM has many built-in macros for HL development. NASM doesn't have very many built-in macros so you do things the long way or use a macro package like NASMX.

The following code might help as a test for working with time. I think C integers are still 8-byte DWORD types so I defined them that way here. The 32-bit version of this code worked fine here, let's hope this 64-bit translation still works.  ;D

Code: (ntime.asm) [Select]
;;; ntime.asm - displays the current time information.

    BITS 64

    GLOBAL main

    %define STACK_ALIGN     sub rsp, 8 ; stack adjustment for calling functions.
    %define STACK_RESTORE   add rsp, 8 ; restore previous stack alignment.

;;; Procedures from the standard C library.
    EXTERN time
    EXTERN localtime
    EXTERN printf

;;; Data-type from the C time.h header.
    STRUC tm
    .tm_sec      resd 1         ; Seconds (0-60)
    .tm_min      resd 1         ; Minutes (0-59)
    .tm_hour     resd 1         ; Hours (0-23)
    .tm_mday     resd 1         ; Day of the Month (1-31)
    .tm_mon      resd 1         ; Month (0-11)
    .tm_year     resd 1         ; Year - 1900
    .tm_wday     resd 1         ; Day of the week (0-6, Sunday = 0)
    .tm_yday     resd 1         ; Day in the year (0-365, 1 Jan = 0)
    .tm_isdst    resd 1         ; Daylight saving time
    ENDSTRUC

SECTION .data                   ; Intialized data section.

now:    dq 0                    ; Storage for time since Epoch
plt:    dq 0                    ; Storage for pointer returned by localtime

SECTION .rodata                 ; Read-only data section.

strTime:    db "The current time is %d:%d:%d", 10, 0

SECTION .text                   ; Executable data section.

    ;; main : number (string . string) -> number .
    ;; The application entrypoint (main) consumes an
    ;; argument count (argc) and a list of arguments
    ;; from the command line (argv) and produces an
    ;; error code for the operating system.
main:
    STACK_ALIGN

    ;; Quote from (The Linux Programmer's Manual):
    ;;  time() returns the time as the number of seconds since the
    ;;  Epoc, 1970-01-01 00:00:00 +0000 (UTC).
    ;;
    ;;  If `t' is non-NULL, the return value is also stored in the
    ;;  memory pointed to by `t'.
   
    mov rdi, now                ; now = t
    call time                   ; get time

    ;; Quote from (The Linux Programmer's Manual):
    ;;  The localtime() function converts the calendar time `timep'
    ;;  to broken-down time representation, expressed relative to the
    ;;  user's specified timezone.
   
    mov rdi, now                ; timep = now
    call localtime              ; convert to localtime
    mov [plt], rax              ; save pointer to tm structure.
   
    ;; ... do some other stuff ...

    mov rdi, [plt]              ; get pointer to local tm structure.
   
    movzx rcx, dword [rdi + tm.tm_sec]   ; get second
    movzx rdx, dword [rdi + tm.tm_min]   ; get minute
    movzx rsi, dword [rdi + tm.tm_hour]  ; get hour
    mov rdi, strTime                     ; show time
    call printf

    mov rax, 0                  ; return EXIT_SUCCESS to Linux
    STACK_RESTORE
    ret
Title: Re: beginner questions
Post by: jackjps on April 03, 2016, 10:01:52 AM
Code: [Select]
#1
          4-3-2016
Hi Bryant,
I am trying to install nasm 2.12.01
Only place I can see to install NASM is in the zip
expansion "install".
It is only instructions to install which don't
work for me.
I renamed the previous nasmfld to nasmfld2.
Made another blank nasmfld.

jack@jack-myheadache ~/nasmfld $ sh autogen.sh
sh: 0: Can't open autogen.sh
jack@jack-myheadache ~/nasmfld $
 
#2
   Does "resd 1" mean dword? What does the "1" do?
      .tm_sec   resd 1 

#3
Everything I see talks about "printf" going to the screen.
I need to go to a hardware printer. Where can I read how to
do this?

#4
Can't find out how to draw lines from A to B.
This has nothing to do with macros.
Still looking....
Title: Re: beginner questions
Post by: Bryant Keller on April 06, 2016, 02:43:21 AM
#1
          4-3-2016
Hi Bryant,
I am trying to install nasm 2.12.01
Only place I can see to install NASM is in the zip
expansion "install".
It is only instructions to install which don't
work for me.
I renamed the previous nasmfld to nasmfld2.
Made another blank nasmfld.

jack@jack-myheadache ~/nasmfld $ sh autogen.sh
sh: 0: Can't open autogen.sh
jack@jack-myheadache ~/nasmfld $

Code: [Select]
$ wget http://www.nasm.us/pub/nasm/releasebuilds/2.12.02rc1/nasm-2.12.02rc1.tar.gz
--2016-04-05 21:59:50--  http://www.nasm.us/pub/nasm/releasebuilds/2.12.02rc1/nasm-2.12.02rc1.tar.gz
Resolving www.nasm.us (www.nasm.us)... 198.137.202.10, 2001:1868:205::10
Connecting to www.nasm.us (www.nasm.us)|198.137.202.10|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1213813 (1.2M) [application/gzip]
Saving to: ‘nasm-2.12.02rc1.tar.gz’

nasm-2.12.02rc1.tar 100%[=====================>]   1.16M   159KB/s   in 7.4s   

2016-04-05 21:59:58 (160 KB/s) - ‘nasm-2.12.02rc1.tar.gz’ saved [1213813/1213813]

$ tar xvf nasm-2.12.02rc1.tar.gz
nasm-2.12.02rc1/
nasm-2.12.02rc1/preproc.h
nasm-2.12.02rc1/AUTHORS
... a bunch of other files...
$ cd nasm-2.12.02rc1/
nasm-2.12.02rc1$ ./configure && make && sudo make install

The last command will configure, build, then prompt you for your password before installing to the system.


#2
   Does "resd 1" mean dword? What does the "1" do?
      .tm_sec   resd 1 

Documentation for RESD (http://www.nasm.us/xdoc/2.12.01/html/nasmdoc3.html#section-3.2.2)


#3
Everything I see talks about "printf" going to the screen.
I need to go to a hardware printer. Where can I read how to
do this?

I haven't tried this code, but in theory you should do this:
Code: [Select]
;; Printing text to hardware.

BITS 64

GLOBAL main
EXTERN popen
EXTERN pclose
EXTERN fprintf
EXTERN fflush

%define EXIT_SUCCESS 0
%define EXIT_FAILURE 1

%define STACK_ALIGN sub rsp, 8
%define STACK_RESTORE add rsp, 8

SECTION .rodata

szPrinter: db "lpr", 0
szWriteMode: db "w", 0

szSomeMessage: db "Hello, world!\nThis is a PDF!", 0

SECTION .data

fdPrinter: dq 0 ; our file descriptor.

SECTION .text

main: STACK_ALIGN
mov rsi, szWriteMode
mov rdi szPrinter
call popen
mov [fdPrinter], rax

cmp rax, 0
jnz .okay

mov rax, EXIT_FAILURE
STACK_RESTORE
ret

.okay:
mov rsi, szSomeMessage
mov rdi, [fdPrinter]
call fprintf

mov rdi, [fdPrinter]
call pclose

mov rax, EXIT_SUCCESS
STACK_RESTORE
ret


#4
Can't find out how to draw lines from A to B.
This has nothing to do with macros.
Still looking....

As I said earlier in this thread (http://forum.nasm.us/index.php?topic=2204.msg9880#msg9880), you're not going to be able to draw graphics in the terminal, that's not what it's for. You'll need to use one of the libraries I suggested earlier to draw on the console, or bite the bullet and learn to do GUI applications.
Title: Re: beginner questions
Post by: jackjps on April 06, 2016, 09:57:49 AM
...
Title: Re: beginner questions
Post by: spoomyfly on January 03, 2017, 10:30:30 AM
Excuse me, i need help with my code(nasm). May i post it here?(im a newbie)
Title: Re: beginner questions
Post by: Eght on January 03, 2017, 12:16:08 PM
Hello guys.
My task is to change code from MASM to NASM. I changed the code a little bit but it is still not enough. The most important part is the print section. I've seen the documentation about nasm and masn differences, but everything is like a black magic for me. Can you guys give me some advices?

This is sieve of eratosthenes

 
Code: [Select]
; size of array to hold the prime candidates
; (arraySize - 1) is the max prime candidate.

SECTION .data


    arraySize EQU 10000
    array1: dd arraySize dup(0) ; initialize array

    .code

SECTION .text

extern printf
extern scanf

global main

main:

    cls

    xor ecx, ecx ; zeroing, is slightly faster than MOV reg, 0

   fillArrayLoop:
  mov eax, ecx ; Move counter value to eax
  add eax, 2 ; The sieve starts at 2, therefore add 2 to the loop counter
  mov [array1+4*ecx], eax ; Insert value into array
  inc ecx ; Increment counter
  cmp ecx, arraySize ;
  jb fillArrayLoop ; jump below, Jump to loop start is we are not finished



    xor ecx, ecx ; Zero out counter
    loop1: ; This is out outer loop
mov ebx, ecx ; Prepare ebx to be used af counter in innerloop (loop2)
inc ebx ; Inner loop starts at ecx + 1
  cmp [array1+4*ecx], -1 ; Value discarded? So is value -1?
  jne loop2 ; if not jump to inner loop(loop2)
  resume1: ; Resume point
inc ecx ; Increment out primary counter
cmp ecx, arraySize ; Are we done?
jb loop1 ; If not jump to loop start.
jmp theEnd ; All done!

loop2: ; Inner loop
cmp [array1+4*ebx], -1 ; Value discarded?
jne loop3 ; if nor jump to loop3
resume2: ; Resumt point
inc ebx ; Increment inner loop counter
cmp ebx, arraySize ; Are we done?
jb loop2 ; if not go to loop start.
jmp resume1 ; Loop2 dont, return to loop1.
loop3: ; Here we will test if it is a prime...
xor edx, edx ; Zero out edx
xor eax, eax ; Zero out eax
mov eax, [array1+4*ebx] ; Place the number we want to divite in eax
div [array1+4*ecx] ; Divide the numbe in eax with the value from outer loop
cmp edx, 0 ; Check edx for remainder
je nukeIt ; If we have no remainder it the number in eax is not a prime
; therefore we nuke it. (set it to -1)
resume3: ; Resume point
jmp resume2 ; Done, jump to resume point in loop2
    nukeIt:
    mov [array1+4*ebx], -1 ; Not a prime, set it to -1
    jmp resume3 ; Jump to resume point

    printArrayElement: ; Just printing all the primes.
    push ecx ; Preserve ecx
    print str$([array1+4*ecx]), 10, 13 ; Using the masm32 print macro
    inc ebx ; Incrementing a counter used to store the number of primes.
    pop ecx ; Callback the preserved ecx
    jmp resumePrintArray ; Jump to resumepoint in print array.


   theEnd: ; exit point


    xor ecx, ecx ; Zero out.
    xor ebx, ebx ; Zero out.

    printArray:
    cmp [array1+4*ecx], -1 ; Check if we have a prime.
    jne printArrayElement ; If we have jump to printArrayElement.
    resumePrintArray: ; Resume point
    inc ecx ; Incrementing
    cmp ecx, arraySize ; Are we done?
    jb printArray ; If not jump to printArray...

print "Number of primes below "
print str$(arraySize)
print ": "
print str$(ebx), 10, 13

    ret


and console output :
Code: [Select]
nasm -f elf primes.asm && gcc -m32 -o primes primes.o
primes.asm:9: error: comma expected after operand 1
primes.asm:71: error: parser: instruction expected
primes.asm:91: error: symbol `print' redefined
primes.asm:91: error: parser: instruction expected
primes.asm:92: error: symbol `print' redefined
primes.asm:92: error: parser: instruction expected
primes.asm:93: error: symbol `print' redefined
primes.asm:93: error: parser: instruction expected
primes.asm:94: error: symbol `print' redefined
primes.asm:94: error: parser: instruction expected
Title: Re: beginner questions
Post by: Frank Kotler on January 03, 2017, 07:52:49 PM
Hello Spoomyfly,

Welcome to the forum! Yes, you may post your code here. (that was easy!)

You probably want to start a new topic. If possible, use a title that will help someone with similar questions find it. If possible, use "code tags" - just the word "code" in square brackets at the start of your code, and "/code" at the end. Note that this is square brackets "[]" - like a Nasm memory reference - not angle brackets "<>" like html. To help us help you, tell us what you "expect" your code to do, and what it does instead. Looking forward to hearing from you.

Hi Eght,

Welcome to the forum. You already know how to use "code tags". Thanks.

As indicated in your comments, "print" needs to be a macro. Since you're linking to the C library "printf", you probably want to use that, right? "print str$"  is also a macro - also using "printf", probably. We could do this all in one macro and "if the first parameter is str$, print a number" but it is probably easier to use a separate macro - "printint", perhaps. Looks like "cls" also wants to be a macro - I'm surprised you're not getting a warning on that - old version of Nasm? Nasm doesn't use "dup".  Could use "times"...
Code: [Select]
section .data
array times arraySize dd 0
but might be better to do:
Code: [Select]
section .bss
array resd arraySize
Programmer's choice. ("section .bss" is nominally uninitialized, but is, in fact, initialized to zero in any reasonable OS). Speaking of OS, Nasm's "-f elf" is for Linux. Your Masm code almost certainly is not.  Is that what you intend? (no problem - we can do it either way... maybe both...)

You might want to start a new topic rather than append to this rather old one...

Best,
Frank