QDOS TCP/IP programming in Assembler
-
- Aurora
- Posts: 853
- Joined: Tue Dec 17, 2013 1:17 pm
QDOS TCP/IP programming in Assembler
Has anyone done any programming of the QDOS TCP/IP device driver in assembler, or know where I can get some sample assembly code that works, so I can try to figure out exactly how to call the system Traps.
I really don't know anything about programming TCP/IP ports, So I am learning as I go.
I've got some information written by Richard Zidlicky which gives the names of the system Traps and information on the register usage when calling them. But it is all very 'C' orientated (which I don't speak).
I can find lots on TCP/IP and socket programming on the Internet, but it's all in 'C' and nothing in assembler . I've managed to figure out what most of the QDOS Traps should do, but when I try to use them, they either don't do what I expect, give errors (but I don't know what went wrong, or what I did wrong), or they seem inconsistent in their operation.
Every time I think I'm starting to understand how the driver works, it all seems to fall apart. And at the moment all I seem to be doing is taking one step forward, and two steps back.
Thanks in advance
Martin
I really don't know anything about programming TCP/IP ports, So I am learning as I go.
I've got some information written by Richard Zidlicky which gives the names of the system Traps and information on the register usage when calling them. But it is all very 'C' orientated (which I don't speak).
I can find lots on TCP/IP and socket programming on the Internet, but it's all in 'C' and nothing in assembler . I've managed to figure out what most of the QDOS Traps should do, but when I try to use them, they either don't do what I expect, give errors (but I don't know what went wrong, or what I did wrong), or they seem inconsistent in their operation.
Every time I think I'm starting to understand how the driver works, it all seems to fall apart. And at the moment all I seem to be doing is taking one step forward, and two steps back.
Thanks in advance
Martin
Re: QDOS TCP/IP programming in Assembler
Martin,
I've done a lot of TCP/IP socket programming in the past, both hobby and professional - But I have never even tried to do that in assembler. There's just too many data structures to tame in order to do even simple things......
I would propose you should acquire at least a minimum amount of C literacy before you start reading examples (not necessarily trying to write programs, but you should be able to read them. That shouldn't be too hard.
Once you're there I recommend a good book (for example W. Richard Stevens: Unix network programming - Prentic Hall - This is the TCPIP socket bible.) There's also some good, some bad and some ugly free C Socket programming tutorials on the internet - But a book is better, IMHO.
Then you could start translating C examples into assembler.
Or - you just come up with some hands-on examples and ask questions I could probably answer.
Tobias
I've done a lot of TCP/IP socket programming in the past, both hobby and professional - But I have never even tried to do that in assembler. There's just too many data structures to tame in order to do even simple things......
I would propose you should acquire at least a minimum amount of C literacy before you start reading examples (not necessarily trying to write programs, but you should be able to read them. That shouldn't be too hard.
Once you're there I recommend a good book (for example W. Richard Stevens: Unix network programming - Prentic Hall - This is the TCPIP socket bible.) There's also some good, some bad and some ugly free C Socket programming tutorials on the internet - But a book is better, IMHO.
Then you could start translating C examples into assembler.
Or - you just come up with some hands-on examples and ask questions I could probably answer.
Tobias
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
- XorA
- Site Admin
- Posts: 1368
- Joined: Thu Jun 02, 2011 11:31 am
- Location: Shotts, North Lanarkshire, Scotland, UK
Re: QDOS TCP/IP programming in Assembler
I would just bite the bullet and learn C. Should only take about 20 minutes for any competent programmer, there are only 20 keywords Also old school C compilers are pretty predictable about the assembler produced.
G
G
-
- Super Gold Card
- Posts: 716
- Joined: Mon Nov 24, 2014 2:03 pm
Re: QDOS TCP/IP programming in Assembler
Are there any skilled 'C' programmers in the Ql Community?
How long does it take to learn the 'C' language enough to be able to transpose superbasic into 'C'?
EmmBee and I are looking for such a programmer too, as we need to submit a new 'Travelling Salesman Program' to the Clay Mathemeatics Institute, for consideration as a solution to the problem.
Of course we could always suggests that the Institute aquires QPC2, but that would eliminate all means of comparison with existing programs attempting to solve the problem...
Has anyone any ideas or suggestions please?
Regards,
Steve Poole.
How long does it take to learn the 'C' language enough to be able to transpose superbasic into 'C'?
EmmBee and I are looking for such a programmer too, as we need to submit a new 'Travelling Salesman Program' to the Clay Mathemeatics Institute, for consideration as a solution to the problem.
Of course we could always suggests that the Institute aquires QPC2, but that would eliminate all means of comparison with existing programs attempting to solve the problem...
Has anyone any ideas or suggestions please?
Regards,
Steve Poole.
-
- Aurora
- Posts: 853
- Joined: Tue Dec 17, 2013 1:17 pm
Re: QDOS TCP/IP programming in Assembler
Thanks for the response, but I don't really want to go to the trouble of learning C and a compiler for it, just for playing with the IP driver in QDOS.
Besides at some point, would I not have to write something in C/Assembler to actually call the QDOS Trap routines. Say I wanted to use the sendto() function. Wouldn't I have to write the function (or whatever it's called in C) to set up the registers and call the IP_SENDTO Trap#3. Which kind of brings me back full circle at having to access the system Traps directly again.
Unless these routines have already been written? I did find something called, I think it was QLIP , a C program, which I had a quick look at, but I think it may be the code for the QDOS IP driver (or an earlier version of), which converts the QDOS system Trap call to a C system call for the QL emulators underlying operation system.
Martin
Besides at some point, would I not have to write something in C/Assembler to actually call the QDOS Trap routines. Say I wanted to use the sendto() function. Wouldn't I have to write the function (or whatever it's called in C) to set up the registers and call the IP_SENDTO Trap#3. Which kind of brings me back full circle at having to access the system Traps directly again.
Unless these routines have already been written? I did find something called, I think it was QLIP , a C program, which I had a quick look at, but I think it may be the code for the QDOS IP driver (or an earlier version of), which converts the QDOS system Trap call to a C system call for the QL emulators underlying operation system.
Martin
Re: QDOS TCP/IP programming in Assembler
They have. Jonathan Hudson has - More than 15 years ago - written a C68 library that sits on top of the QDOS TCP/IP implementation in QPC2 and uqlx.Martin_Head wrote: Unless these routines have already been written?
http://www.zen35309.zen.co.uk/qdos/qlsocket.zip
Using these, most of the UNIX TCP/IP code found on the internet can just be re-compiled with C68 and, normally, just runs.
Tobias
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
-
- Aurora
- Posts: 853
- Joined: Tue Dec 17, 2013 1:17 pm
Re: QDOS TCP/IP programming in Assembler
I think this is the QLIP thing I was talking about. I will give it a deeper look at.tofro wrote:They have. Jonathan Hudson has - More than 15 years ago - written a C68 library that sits on top of the QDOS TCP/IP implementation in QPC2 and uqlx.
http://www.zen35309.zen.co.uk/qdos/qlsocket.zip
Using these, most of the UNIX TCP/IP code found on the internet can just be re-compiled with C68 and, normally, just runs.
Tobias
Could I ask a few a few basic questions about programming sockets?
I am trying to do a basic UDP peer to peer connection between two computers. On one I am using QPC2, and on the other a simple Visual basic program (a chat program from the help files), which just sends text to, or receives text from, a winsock control. I am using the Visual basic because I thought if I tried to use two QPC2's and they did not communicate, I would not know if it was a sending or a receiving problem.
I can get a two way connection working when using send() and recev(). But when I try to use sendto() and recevfrom(), sendto() seems to work Ok, but recevfrom() does not. It gives me a Bad Parameter error. I'm guessing it's to do with the sockaddr structure being wrong.
So first question, For recevfrom() does the sockaddr structure need to be set up with the details of the other computer before the function is called, so that you are telling it to receive a message from that computer specifically, or should it be set up empty so that the function fills in the information, so that you can tell where it has come from?
When opening a channel eg "UDP_172.16.0.5:1002" for send() and recev() you need the host and the port? But do you need the host and the port specified for sendto() and recevfrom()? this is kind of tied in with the question above.
Binding, When do you, and when don't you need to use it? Am I right that it's saying "this is the port number of this computer that I will be sending and receiving data on". The sockaddr structure for this command would contain the port number, but what about the IP address, is it the IP address of this computer?
When I have tried to use bind() and I get a Bad Parameter error, I think I am not constructing the sockaddr structure correctly.
Ports, What are a safe port numbers to use? maybe I am using the wrong ones? I have been using 1001 and 1002 because that's what the Visual basic program used. Some of the stuff I have seen on the Internet suggests using ports from about 50000 up to 65535.
The send(), recev() program I have which works, basically goes
open udp_IP address of other computer:port number
send() some text
which appears on the other computer
the other computer then sends some text
recv()
the text is received on this computer
The other computer has opened the IP address of this computer and a port number. But I have not told this computer what port to use, so how does it know to read from this port?
Sorry to have gone on a bit, and I'm sure I could find lots more question.
Martin
- XorA
- Site Admin
- Posts: 1368
- Joined: Thu Jun 02, 2011 11:31 am
- Location: Shotts, North Lanarkshire, Scotland, UK
Re: QDOS TCP/IP programming in Assembler
Ports below 1024 are reserved for administrator/root always use a port 1025+ for user applications, best for 5000+ as less likely to collide with other common services.Martin_Head wrote: Ports, What are a safe port numbers to use? maybe I am using the wrong ones? I have been using 1001 and 1002 because that's what the Visual basic program used. Some of the stuff I have seen on the Internet suggests using ports from about 50000 up to 65535.
Get yourself a copy of wireshark to install on the PC, this will show you everything that is going on network wise. Its essential tool for debugging network issues.
G
Re: QDOS TCP/IP programming in Assembler
Please keep us informed of progress with this project, Martin. It's a subject which doesn't get much attention in the QL scene and I'll follow it with interest.
I have dabbled a little with the tcp devices from BASIC and it's surprising what can be achieved just from BASIC in some cases. Here's a little program from Jon Dent which shows how to read email headers and the first few lines of a plain text email:
For anyone who hasn't studied the tcp driver, you simply open a channel to the resource you want, preceded by tcp_ and ending with the port number after a colon (see line 100). You then talk to the server with normal BASIC commands like PRINT and INPUT. You need to study the official documents for exactly what commands are supported - there's plenty of documentation out there. What we're short of is examples for QL users to study. If anyone wishes to contribute examples I'll happily host them on my website, probably by starting a page like I did for the QL-SD in order to kick-start interest.
I have dabbled a little with the tcp devices from BASIC and it's surprising what can be achieved just from BASIC in some cases. Here's a little program from Jon Dent which shows how to read email headers and the first few lines of a plain text email:
Code: Select all
100 OPEN_IN #8,"tcp_mail.isp.net:110": REM your account
110 inst$="": stage=0
120 crlf$= CHR$(13) & CHR$(10)
130 REPeat
140 a$= INKEY$(#8,100)
150 IF a$<>"":inst$= inst$ & a$
160 PRINT a$;
170 SELect ON stage
180 =0:
190 IF "OK" INSTR inst$ THEN
200 inst$= ""
210 PRINT #8, "USER user.name.here";crlf$; : REM your user name
220 stage= 1
230 END IF
240 =1:
250 IF "OK" INSTR inst$ THEN
260 inst$= ""
270 PRINT #8, "PASS password.here";crlf$; : REM your password
280 stage= 2
290 END IF
300 =2:
310 IF "OK" INSTR inst$ THEN
320 inst$= ""
330 PRINT #8, "LIST";crlf$;
340 stage= 3
350 END IF
360 =3:
370 IF "OK" INSTR inst$ THEN
380 PRINT #0,"view which mail number ? 0 to QUIT":
390 INPUT #0,number$
400 IF number$<>0
410 PRINT #8,"TOP ";number$;" 5";crlf$;
420 ELSE
430 PRINT #8,"QUIT";crlf$;
440 END IF
450 CLS:CLS #0
460 stage= 2
470 END IF
480 END SELect
490 END REPeat
--
All things QL - https://dilwyn.qlforum.co.uk/index.html
All things QL - https://dilwyn.qlforum.co.uk/index.html
Re: QDOS TCP/IP programming in Assembler
@Dilwyn: There actually is quite a lot possible using SuperBASIC only - What you can't do, is writing a server, that is, you can only create the client side of a socket connection in S*BASIC and always need to rely on some other OS/language to implement the "other side" (Just because listen, bind and recvfrom have no implementation in S*BASIC - So implementing some new toolkit would actually solve this).
Martin,
when you use recvfrom (), you need to actually allocate some space for the call to store the address of the sender. It should be empty (it's about to be overwritten by the recvfrom() call anyhow), and have enough space for an IPv4 adress, that is, you must allocate memory for a struct sockaddr_in structure, even if the prototype only asks for a struct sockaddr. If there's not enough space, recvfrom() will complain.
The point is, in socket programming you have a lot of different cases handled by the same operating system calls. You need to know what case you're handling before you can actually fill in the proper data. Peer-to-peer communications between two UDP end-points is actually the simplest approach, so you have chosen the right thing to start with.
You need to
Tobias
Martin,
when you use recvfrom (), you need to actually allocate some space for the call to store the address of the sender. It should be empty (it's about to be overwritten by the recvfrom() call anyhow), and have enough space for an IPv4 adress, that is, you must allocate memory for a struct sockaddr_in structure, even if the prototype only asks for a struct sockaddr. If there's not enough space, recvfrom() will complain.
The point is, in socket programming you have a lot of different cases handled by the same operating system calls. You need to know what case you're handling before you can actually fill in the proper data. Peer-to-peer communications between two UDP end-points is actually the simplest approach, so you have chosen the right thing to start with.
You need to
- Open a socket at each end - The address you give to the endpoint actually doesn't really matter - It's going to be overridden by sendto()/recvfrom() anyhow later. For reasons of simplicity, just use "127.0.0.1" or your computer's "real" IP address. Note the socket type must be SOCKET_DGRAM - i.e, UDP.
- Bind the socket to a port (should be otherwise un-used and above at least 1024, better above 5000)
Note with some of the open() keys in combination with a properly formed device name, you can actually do both of the above steps in one - Sender does a sendto() . Needs a fully-specified IPv4 address of the receiver.
- Receiver does a recvfrom(). Address needs to be supplied empty, but with enough space to hold a sockaddr_in, otherwise recvfrom() will fail.
Tobias
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO