I wanted to get a bit into FASM. I already have some experience with another assembly-language, which would be for the myAVR micro-controller.
I tried getting unbuffered input from the standard-stream without using a library, but instead resorting to syscalls.
Apparently ioctl should do fine for this (I'm on Linux), though I seem to not get the termios-struct right.
Here's my code:
[code]format elf executable
entry main
;syscalls
SYSCALL_EXIT equ 1
SYSCALL_READ equ 3
SYSCALL_IOCTL equ 54
;standard I/O
STDIN equ 0
;ioctl subfunctions
TCGETS equ 0x5401
TCSETS equ 0x5402
;struct termios
struc termios{
.c_iflag rd 1 ;input mode flags
.c_oflag rd 1 ;output mode flags
.c_cflag rd 1 ;control mode flags
.c_lflag rd 1 ;local mode flags
.c_line rb 1 ;line discipline
.c_cc rb 32 ;control characters
.c_ispeed rd 1 ;input speed
.c_ospeed rd 1 ;output speed
}
;termios flags
ICANON equ 2 ;Do erase and kill processing
ECHO equ 8 ;Enable echo
;static data
segment readable writable
oldtermios termios
newtermios termios
;--------
segment executable
main:
;get old termios mode
mov eax, SYSCALL_IOCTL
mov ebx, STDIN
mov ecx, TCGETS
mov edx, oldtermios
;copy termios
; mov esi, oldtermios
; mov edi, newtermios
; mov ecx, 4
; repz movs dword [edi], [esi]
; mov ecx, 33
; repz movs byte [edi], [esi]
; mov ecx, 2
; repz movs dword [edi], [esi]
;set new termios
; and dword [newtermios.c_lflag], not (ICANON or ECHO)
mov eax, SYSCALL_IOCTL
mov ebx, STDIN
mov ecx, TCSETS
mov edx, oldtermios ;newtermios
int 0x80
;get input
mov eax, SYSCALL_READ
mov ebx, STDIN
mov ecx, esp
mov edx, 1
int 0x80
;reset termios
mov eax, SYSCALL_IOCTL
mov ebx, STDIN
mov ecx, TCSETS
mov edx, oldtermios
; int 0x80
;exit
mov eax, SYSCALL_EXIT
mov ebx, 0
int 0x80[/code]
I'm getting the termios and without modification setting it again, but input is broken after I assemble and run it. It also doesn't wait for any input upon launching.
Here's the struct as in /usr/include/bits/termios.h
[code]typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 32
struct termios
{
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1
#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1
};[/code]
And as a little side-question: is there a more convenient way of copying structs?
I don't have an account there, but since I have one here I thought I'd ask.
You're probably right though, there are not too many assembly-programmers (apart maybe from the Arduino guys; didn't follow their thread).
Copying the struct like this seems way too obvious. I guess I just was costumed to a C-way of thinking...
I will look into the struct macro,I just began FASM by looking at a NASM tutorial and getting some parts of the FASM manual ;)
[QUOTE=ZeekyHBomb;22141906]You're probably right though, there are not too many assembly-programmers (apart maybe from the Arduino guys; didn't follow their thread).[/QUOTE]
Arduinos have a Wiring based language.
nasm supremacy
If the struc and struct macros don't add alignment padding, try adding your own padding for the single-byte c_line field.
Nope. Tried adding 3 bytes before c_line, after, before the whole data and after the whole data.
I should try writing the contents of termios to file, write a C pendant and compare the two files.
[editline]07:55PM[/editline]
How do I access errno?
This code returns 1, though the file gets created
[code]format elf executable
entry main
;syscalls
SYSCALL_EXIT equ 1
SYSCALL_WRITE equ 4
SYSCALL_CLOSE equ 6
SYSCALL_CREAT equ 8
SYSCALL_IOCTL equ 54
;standard I/O
STDIN equ 0
;open modes
S_IWUSR equ 200 ;write permission
S_IRUSR equ 400 ;read permission
;ioctl subfunctions
TCGETS equ 0x5401
TCSETS equ 0x5402
;struct termios
struc termios{
.c_iflag rd 1 ;input mode flags
.c_oflag rd 1 ;output mode flags
.c_cflag rd 1 ;control mode flags
.c_lflag rd 1 ;local mode flags
.c_line rb 1 ;line discipline
.c_cc rb 32 ;control characters
.c_ispeed rd 1 ;input speed
.c_ospeed rd 1 ;output speed
;.unused rb 3 ;3 byte padding
}
;termios flags
ICANON equ 2 ;Do erase and kill processing
ECHO equ 8 ;Enable echo
;static data
segment readable writeable
oldtermios termios
newtermios termios
filename db "termios.txt", 0
fd rd 1
;--------
segment executable
main:
;open file
mov eax, SYSCALL_CREAT
mov ebx, filename
mov ecx, S_IWUSR or S_IRUSR
int 0x80
mov ecx, 1 ;return code 1
test eax, eax
js exit
mov [fd], eax
;get old termios mode
mov eax, SYSCALL_IOCTL
mov ebx, STDIN
mov ecx, TCGETS
mov edx, oldtermios
;write file
mov eax, SYSCALL_WRITE
mov ebx, fd
mov ecx, oldtermios
mov edx, 6 * 4 + 33
int 0x80
mov ecx, 1 ;return code 2
test eax, 6 * 4 + 33
jne exit
mov ecx, 0 ;return code 0
exit:
;close file
mov eax, SYSCALL_CLOSE
mov ebx, fd
int 0x80
;exit
mov eax, SYSCALL_EXIT
mov ebx, ecx
int 0x80[/code]
[editline]10:56PM[/editline]
Okay, so I got around to the errno thanks to [url=http://www.lxhp.in-berlin.de/lhpsyscal.html]this page[/url]. The man-pages are only for C :(
It's stored (negated) in eax.
The fd after SYSCALL_WRITE shoulda been [fd].
So, now it writes 57 bytes, but all are 0.
There are indeed 3 bytes padding and after updating ... still all 0.
My C-version outputs a bunch of different bytes just fine.
Well, that was dumb. I was missing an int 0x80 after SYSCALL_IOCTL. In both assembly-files :P
Works fine now :D
Sorry, you need to Log In to post a reply to this thread.