I found code in 80836 DOS assembly that I'd like to port to 32-bit Linux assembly, using AT&T syntax.
I found site that explains some differences but only about registers. EX:
So I got problems converting following code:
input:
mov ah, 00h
int 16h
cmp ah, 1ch
je exit
sub al, 30h
sub al, 37h
sub al, 57h
mov ah, 02h
mov dl, al
int 21h
mov dl, 20h
int 21h
exit:
int 20h
I am converting this code
I think that:
The worst problem is with interrupts since in AT&T assembly it's like:
SYSCALL = 0X80
SYSEXIT = 1
EXIT_SUCCESS = 0
SYSREAD = 3
SYSWRITE = 4
STDIN = 0
STDOUT = 1
And in DOS16, 16h? 20h? 21h? oh man, and even then int 20h acts as interrupt and as value (mov dl, 20h)? so confusing.
Can someone help me?
@EDIT I converted it like this, but I got segmentation fault error. I am almost sure it's about interrupts..
.data
.text
.global _start
_start:
input:
movb $0x0,%ah
int $0x16
cmpb $0x1c,%ah
je exit
number:
cmpb $'0', %al
jb input
cmpb $'9', %al
ja uppercase
subb $0x30,%al
call process
jmp input
uppercase:
cmpb $'A', %al
jb input
cmpb $'F', %al
ja lowercase
subb $0x37,%al
call process
jmp input
lowercase:
cmpb $'a', %al
jb input
cmpb $'f', %al
ja input
subb $0x57,%al
call process
jmp input
loop input
process:
movb $4,%ch
movb $3,%cl
movb %al,%bl
convert:
movb %bl,%al
rorb %cl,%al
andb $01,%al
addb $0x30,%al
movb $0x2,%ah
movb %al,%dl
int $0x21
decb %cl
decb %ch
jnz convert
movb $0x20,%dl
int $0x21
ret
exit:
int $0x20
Anyone?
Probably the main problem of your code "conversion" is that you seem to connect some ideas with the terms "80836 assembly" and "at&t" that don't really apply.
Although this might just be a matter of naming conventions there is no "80386 assembly" vs. "at&t" difference but a "intel" vs. "at&T syntax" difference as both intel syntax and at&t syntax can be used to describe x86 assembly code.
If you are using GNU assembler (I don't know any other x86 assembler using AT&T syntax instead of intel) you might just want to use .intel_syntax
and stay with the intel syntax used in your reference material instead.
.intel_syntax noprefix
; your code in intel syntax here
.att_syntax prefix
; code in at&t syntax here
Don't forget to switch to 16-bit mode.code16
if you intend to use it in real mode.
The far the bigger problem with your question seems to be that you are not only trying to transform the code from using "intel-syntax" to using "at&t-syntax" but rather to port it to a. another addressing mode and b. another operating system.
Especially your question about interrupt calling conventions leads me to the assumption you are trying to port 16-bit DOS code to some kind of 32-bit code running on a LINUX machine.
Just "reusing" the given code to perform system calls won't be possible by simply replacing numbers as there a different calling conventions involved.
Things you might try to fix your code include using syscall read instead of BIOS interrupt to read from stdin
storage:
.ascii " "
# ...
movl $3, %eax # syscall number
# (check syscall.h to see if it's 3 on your system)
movl $0, %ebx # file descriptor (0 designating stdin)
movl $storage, %ecx
movl $1, %edx # number of chars to read
int $0x80
Code utilizing DOS syscall mechanism int 0x21 would have to be fixed in addition using something like
movl $4, %eax # syscall number write
movl $0, %ebx # file descriptor (1 designating stdout)
movl $storage, %ecx
movl $1, %edx # number of chars to write
int $0x80
The last step should be fixing the exit syscall:
movl $1, %eax # syscall number exit
movl $0, %ebx # it doesn't hurt to set a reasonable exit code here.
int $0x80
Regarding DOS syscalls taking a look at http://en.wikipedia.org/wiki/MS-DOS_API should help to understand what int 0x20
and int 0x21
are used for in your example code.
Seraching for BIOS interrupt also wikipedia is your friend: http://en.wikipedia.org/wiki/Bios_interrupt should answer your question.
in your case it is int 0x16
with 0
in ah
- thus: read character.