• termios in FASM
    7 replies, posted
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.