A bootloader that I am making doesn't get any IRQ12 - mouse
The computer in which I test my operating system is a laptop with a touchpad. When I power the computer on, it reads the keyboard, but after I touch the touchpad, it doesn't read the touchpad nor the keyboard either.
And I also use qemu and on qemu it doesn't read the mouse but keeps reading the keyboard.
This is the code that I use for the mouse:
#ifndef _MOUSE
#define _MOUSE
#include "base.cpp"
#include "math.cpp"
#include "vector.cpp"
//#include "console.cpp"//------
class Mouse
{
public:
Bool key_pressed[3];
Vector2 position;
private:
Vector<Ubyte> bytes_buffer;
double mouse_area_y_respect_x;
void limit_inside_area()
{
limit_inside(position.x,0,1);
limit_inside(position.y,0,mouse_area_y_respect_x);
}
Bool process_stroke()
{
if(bytes_buffer.size()<4) return false;
else
{
position.x=0;
limit_inside_area();
bytes_buffer.resize(bytes_buffer.size()-4);
return true;
}
}
Ubyte in_port_0x64()
{
Ubyte val;
asm("in al,0x64;":"=a"(val));
return val;
}
Ubyte in_port_0x60()
{
Ubyte val;
asm("in al,0x60;":"=a"(val));
return val;
}
void out_port_0x60(Ubyte byte)
{
asm("out 0x60,%%al"::"a"(byte));
}
void out_port_0x64(Ubyte byte)
{
asm("out 0x64,%%al"::"a"(byte));
}
void wait_for_device(Uint64 mode)
{
if(mode==0)
{
for(Uint64 n=0;n<10000;n++)
{
Ubyte val=in_port_0x64();
if((val&1)==1) break;
}
}
else
{
for(Uint64 n=0;n<10000;n++)
{
Ubyte val=in_port_0x64();
if((val&2)==0) break;
}
}
}
void send_to_device(Ubyte byte)
{
wait_for_device(1);
out_port_0x64(0xD4);
wait_for_device(1);
out_port_0x60(byte);
}
Ubyte wait_for_device_acknowledge()
{
wait_for_device(0);
return in_port_0x60();
}
public:
void initialize(double _mouse_area_y_respect_x)
{
for(Uint64 n=0;n<3;n++)
{
key_pressed[n]=false;
}
mouse_area_y_respect_x=_mouse_area_y_respect_x;
if(mouse_area_y_respect_x>=0.1 && mouse_area_y_respect_x<=100){}
else if(mouse_area_y_respect_x<0.1) mouse_area_y_respect_x=0.1;
else if(mouse_area_y_respect_x>100) mouse_area_y_respect_x=100;
else
{
mouse_area_y_respect_x=1;
}
position=Vector2(0.5,mouse_area_y_respect_x/2);
}
void initialize_device()
{
asm("cli");
wait_for_device(1);
out_port_0x64(0xA8);
wait_for_device_acknowledge();
wait_for_device(1);
out_port_0x64(0x20);
wait_for_device(0);
Ubyte status=in_port_0x60();
status=status|2;
wait_for_device(1);
out_port_0x64(0x60);
wait_for_device(1);
out_port_0x60(status);
send_to_device(0xF6);
wait_for_device_acknowledge();
send_to_device(0xF4);
wait_for_device_acknowledge();
asm("sti");
}
void update_from_interrupt()
{
Ubyte data=in_port_0x60();
input_byte[input_byte_cycle]=data;
input_byte_cycle++;
if(input_byte_cycle>3)
{
input_byte_cycle=0;
position.x=0;
}
position.x=0;
//bytes_buffer.push_back(data);
//if(bytes_buffer.size()>10000) bytes_buffer.resize(0);
}
Ubyte input_byte[4];
Uint64 input_byte_cycle=0;
void update()
{
//while(bytes_buffer.size()>0 && process_stroke()){}
}
};
static Mouse*CURRENT_MOUSE;
#endif
This is the point where I call the function "initialize_device()" in the bootloader:
Mouse mouse;
mouse.initialize(768.0/1024);
mouse.initialize_device();
CURRENT_MOUSE=&mouse;
set_interrupts_handler((Uint64)&interrupts_handler);
//the BIOS call for VESA
call_assembly(0,0x4f02,VESA_MODE,0,0,0,0,0,0x10);
Uint64 time=0;
while(1)
{
for(Uint64 n=0;n<1;n++)
{
CURRENT_KEYBOARD->update();
CURRENT_MOUSE->update();
}
time++;
console.draw(screen,time/10);
screen.circlefill((CURRENT_MOUSE->position*1024).toPos(),10,0xffffff);
if(bootloader_info.VESA->BitsPerPixel==24) screen.draw(bootloader_info.VESA->PhysBasePtr);
else screen.draw_alpha(bootloader_info.VESA->PhysBasePtr);
}
And the interrupt handler which handles some of the interrupts:
void interrupts_handler()
{
Uint64 interrupt_number=get_interrupt_number_interrupts_handler();
if(interrupt_number==8)
{
TIME++;
}
else
{
CURRENT_CONSOLE->printhex(interrupt_number);//---------------------
CURRENT_CONSOLE->printf(" ");
if(interrupt_number==9)
{
Uint64 var;
asm("in al,0x60;"
/*"out 0x61,al;"*/:"=a"(var));
Ubyte keycode=var;
CURRENT_KEYBOARD->update_from_interrupt(var);
}
else if(interrupt_number==0x74)
{
CURRENT_MOUSE->update_from_interrupt();
}
else if(interrupt_number==0x0f)
{
}
}
}
This is only a small part of the code, but I have put what I think it's most important.
And the types (defined in base.cpp):
typedef char Int8;
typedef unsigned char Uint8;
typedef short int Int16;
typedef unsigned short int Uint16;
typedef int Int32;
typedef unsigned int Uint32;
typedef long long int Int64;
typedef unsigned long long int Uint64;
typedef Int8 Byte;
typedef Uint8 Ubyte;
typedef Ubyte* Ptr;
typedef Ubyte Bool;
With "CURRENT_CONSOLE->printhex(interrupt_number);" in the interrupt handler, I have made it print the numbers of the interrupts it gets, that's how I know that I don't get any IRQ12, (I have not remapped the PIC).
The other part of the interrupt handler, which is in nasm assembly:
LONG_MODE_BASIC_INTERRUPTION_HANDLER:
%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_E 1
push rax
mov al,%1
jmp .handler
%endmacro
%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 1
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x01
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x02
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x03
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x04
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x05
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x06
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x07
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x08
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x09
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0A
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0B
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0C
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0D
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0E
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0F
%endmacro
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x10
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x20
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x30
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x40
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x50
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x60
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x70
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x80
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x90
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xA0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xB0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xC0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xD0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xE0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xF0
.handler:
cmp al,8
je .timer_or_double_fault
cmp al,9
je .keyboard
cmp al,0x0d
je .general_protection_fault
cmp al,0x0e
je .page_fault_or_floppy_disc
cmp al,0x0f
je .strange_or_spurious
cmp al,0x74
je .mouse
call NOT_HANDLED_INTERRUPT_MESSAGE
jmp $
.timer_or_double_fault:
;pop rbx
;pop rcx
;cmp rcx,0
;je .double_fault
;push rcx
;push rbx
push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,0
je .double_fault
pop rcx
pop rbx
jmp .timer
.keyboard:
.mouse:
.strange_or_spurious:
.timer:
push rbx
mov rbx,[POINTER_TO_INTERRUPTS_HANDLER]
cmp rbx,0
je .no_cpp
mov [INTERRUPT_NUMBER_FOR_HANDLER],al
PUSHA64
call [POINTER_TO_INTERRUPTS_HANDLER]
POPA64
.no_cpp:
pop rbx
mov al,0x20
out 0x20,al
jmp .end
.double_fault:
push rbx
call DOUBLE_FAULT_MESSAGE
BITS 64
.general_protection_fault:
call GENERAL_PROTECTION_FAULT_MESSAGE
mov al,0x20
out 0x20,al
jmp .end
.page_fault_or_floppy_disc:
push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,32
jl .page_fault
pop rcx
pop rbx
mov al,0x20
out 0x20,al
jmp .end
.page_fault:
push rbx
;-----------------------------
mov al,0x20
out 0x20,al
jmp .end
.end:
pop rax
iretq
EDIT:
I have changed the handler in assembly:
LONG_MODE_BASIC_INTERRUPTION_HANDLER:
%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_E 1
push rax
mov al,%1
jmp .handler
%endmacro
%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 1
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x01
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x02
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x03
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x04
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x05
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x06
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x07
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x08
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x09
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0A
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0B
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0C
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0D
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0E
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0F
%endmacro
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x10
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x20
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x30
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x40
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x50
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x60
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x70
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x80
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x90
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xA0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xB0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xC0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xD0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xE0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xF0
.handler:
cmp al,8
je .timer_or_double_fault
cmp al,9
je .keyboard
cmp al,0x0d
je .general_protection_fault
cmp al,0x0e
je .page_fault_or_floppy_disc
cmp al,0x0f
je .strange_or_spurious
cmp al,0x74
je .mouse
call NOT_HANDLED_INTERRUPT_MESSAGE
jmp $
.timer_or_double_fault:
;pop rbx
;pop rcx
;cmp rcx,0
;je .double_fault
;push rcx
;push rbx
push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,0
je .double_fault
pop rcx
pop rbx
jmp .timer
.keyboard:
.mouse:
.strange_or_spurious:
.timer:
push rbx
mov rbx,[POINTER_TO_INTERRUPTS_HANDLER]
cmp rbx,0
je .no_cpp
mov [INTERRUPT_NUMBER_FOR_HANDLER],al
PUSHA64
call [POINTER_TO_INTERRUPTS_HANDLER]
POPA64
.no_cpp:
mov al,0x20
mov bl,[INTERRUPT_NUMBER_FOR_HANDLER]
cmp bl,0x70
jl .IRQ0_7
out 0xA0,al
.IRQ0_7:
out 0x20,al
pop rbx
jmp .end
.double_fault:
push rbx
call DOUBLE_FAULT_MESSAGE
BITS 64
.general_protection_fault:
call GENERAL_PROTECTION_FAULT_MESSAGE
jmp .end
.page_fault_or_floppy_disc:
push rbx
push rcx
mov rcx,[rsp-3]
mov rbx,[rsp-4]
cmp rcx,32
jl .page_fault
pop rcx
pop rbx
mov al,0x20
out 0x20,al
jmp .end
.page_fault:
push rbx
;-----------------------------
jmp .end
.end:
pop rax
iretq
EDIT 2:
Interrupt handler in assembly:
%macro PUSHA64 0
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
%endmacro
%macro POPA64 0
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
%endmacro
LONG_MODE_BASIC_INTERRUPTION_HANDLER:
%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_E 1
push rax
mov al,%1
jmp .handler
%endmacro
%macro LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 1
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x01
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x02
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x03
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x04
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x05
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x06
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x07
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x08
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x09
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0A
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0B
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0C
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0D
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0E
LONG_MODE_BASIC_INTERRUPTION_HANDLER_E %1+0x0F
%endmacro
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x00
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x10
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x20
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x30
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x40
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x50
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x60
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x70
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x80
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0x90
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xA0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xB0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xC0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xD0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xE0
LONG_MODE_BASIC_INTERRUPTION_HANDLER_16E 0xF0
.handler:
PUSHA64
cmp al,0x08
je .double_fault
cmp al,0x0d
je .general_protection_fault
cmp al,0x0e
je .page_fault
cmp al,0x70
je .timer
cmp al,0x71
je .keyboard
cmp al,0x76
je .floppy_disc
cmp al,0x7c
je .mouse
cmp al,0x77
je .strange_or_spurious
call NOT_HANDLED_INTERRUPT_MESSAGE
jmp $
.keyboard:
.mouse:
.strange_or_spurious:
.timer:
.floppy_disc:
mov rbx,[POINTER_TO_INTERRUPTS_HANDLER]
cmp rbx,0
je .no_cpp
mov [INTERRUPT_NUMBER_FOR_HANDLER],al
call [POINTER_TO_INTERRUPTS_HANDLER]
.no_cpp:
mov al,0x20
mov bl,[INTERRUPT_NUMBER_FOR_HANDLER]
cmp bl,0x78
jl .IRQ0_7
out 0xA0,al
.IRQ0_7:
out 0x20,al
jmp .end
.double_fault:
call DOUBLE_FAULT_MESSAGE
jmp .end_pop_error_code
.general_protection_fault:
call GENERAL_PROTECTION_FAULT_MESSAGE
jmp .end_pop_error_code
.page_fault:
jmp .end_pop_error_code
.end:
POPA64
pop rax
iretq
.end_pop_error_code:
POPA64
pop rax
pop qword[.void]
iretq
.void: dq 0
code that remaps the PICs:
BITS 32
io_wait:
push ecx
mov ecx,100
.loop:
loop .loop
pop ecx
ret
; Input:
; al: first PIC's offset
; bl: second PIC's offset
remap_PICs:
PIC1_COMMAND equ 0x20
PIC2_COMMAND equ 0xA0
PIC1_DATA equ 0x21
PIC2_DATA equ 0xA1
ICW1_INIT_WITH_ICW1_ICW4 equ 0x11
ICW4_8086 equ 0x01
mov ch,al
mov dh,bl
in al,PIC1_DATA
mov cl,al
in al,PIC2_DATA
mov dl,al
mov al,ICW1_INIT_WITH_ICW1_ICW4
out PIC1_COMMAND,al
call io_wait
out PIC2_COMMAND,al
call io_wait
mov al,ch
out PIC1_DATA,al
call io_wait
mov al,dh
out PIC2_DATA,al
call io_wait
mov al,4
out PIC1_DATA,al
call io_wait
mov al,2
out PIC2_DATA,al
call io_wait
mov al,ICW4_8086
out PIC1_DATA,al
call io_wait
out PIC2_DATA,al
call io_wait
mov al,cl
out PIC1_DATA,al
mov al,dl
out PIC2_DATA,al
ret
You have multiple problems:
1 you need to save all the registers (and restore them) at interrupt entry. If you don’t do this, you cannot resume after the interrupt handler ran. This is subtle to debug, because if you are idle before the interrupt, you won’t notice the corrupted register state.
2 you need to issue the ICWs to the PICs. Somebody mentioned this in the comments, but without the ICWs, you really don’t know what the PIC is going to do with an interrupt. Remap the interrupts to 0x20..0x30.
3 you need to choose how you interact with the PIC; the current vogue is to use the interrupt entry to both mask and acknowledge the interrupt, which frees other interrupts to occur.
you have intermingled your exceptions with interrupts. This is problematic for two reasons: first you shouldn’t touch the PIC unless it is for a real interrupt; second some exceptions push an extra value on the stack which you need to accommodate.
So, save more registers, initialize the PICs, separate the exceptions from the interrupts.
Addendum to updated source:
1. I don’t see any code where you initialized the PICs.
2. That messed up assembler you are using is hiding way too much: if you have set the real interrupt base(s) to be 0x70 and 0x78, I expect to see code corresponding to these entries, and code which sets the corresponding IDT entries. I see neither.
You have exhausted my patience; you haven’t provided the requested source and the source you have provided isn’t sensible. I don’t see any way to help you.
Related
x86_64 nasm jumps to the wrong location
I'm working on code to enumerate the PCI bus, but have found that the jz statement for the loop over each device jumps to the wrong location (not even a label). The register function should be getting called for each time cmp ax, 0xffff is inequal, which should be more than once. It is only getting called once. register: ; eax = edi = config offset of the function mov dx, ADDR_PRT add eax, 0x08 in eax, dx shr eax, 16 mov dx, ax call checkpoint mov eax, edi rmsd: cmp dx, 0x0601 ; mass storage devices je ahci_register ; register an AHCI controller ret ; couldn't find it, ignore it pci_init: mov edi, 0x80000000 ilp0: mov rax, rdi mov dx, ADDR_PRT out dx, eax mov dx, DATA_PRT in eax, dx cmp ax, 0xffff je ilp0c0 push rdi mov rax, rdi call register pop rdi ilp0c0: add rdi, 0x100 test edi, 0xff000000 ; code jupms to the line before this jz ilp0 ret Code is assembled as a PE file and then linked using lld-link and run using EFI.
MASM x86-64 scanf not reading spaces
I have simple 64 bit assembly program that we are doing for class. It is supposed to take user input (string) and return that string with lowercase letters into uppercase and uppercase into lowercase. With what I have, it will read anything until it finds a space and this will not read anymore after that. So if I input "test", it will output "TEST". If I input "test Test" it will output "TEST". However, if I add spaces before the first word, it would output the first word but removes the spaces. For example: input " TesT", output: "tESt". Anyone know how I can go about fixing this? Here is my whole program: ;Author: Keenan Kaufman ;Date: 10/20/2017 INCLUDELIB msvcrt.lib printf PROTO scanf PROTO exit PROTO .DATA CRLF BYTE 0Dh, 0Ah, 0 ;carriage return msgHeader BYTE "Enter a mixed case string: ", 0 message BYTE 20 DUP(0), 0 target BYTE SIZEOF message DUP(?), 0Dh, 0Ah, 0 msgformat BYTE "%20s", 0 .CODE main PROC ;Display request for user input lea rcx, msgHeader call printf ;obtain user input lea rcx, msgformat lea rdx, message call scanf lea rsi, message lea rdi, target jmp GETNEXT GETNEXT: mov al, [rsi] cmp al, 0 je ENDCASE cmp al, 'z' ja NOCHANGE cmp al, 'A' jb NOCHANGE cmp al, 'a' jae TOUPPER cmp al, 'Z' jbe TOLOWER TOUPPER: sub al, 32 mov [rdi], al inc rdi inc rsi jmp GETNEXT TOLOWER: add al, 32 mov [rdi], al inc rdi inc rsi jmp GETNEXT NOCHANGE: mov [rdi], al inc rdi inc rsi jmp GETNEXT ENDCASE: jmp FINISH FINISH: ;Display target lea rcx, target call printf lea rcx, CRLF call printf mov rax, 0 call exit main ENDP END
Yes, that is a feature of scanf. Here is the Linux man page for scanf which, for the %s format, says: s Matches a sequence of non-white-space characters; the next pointer must be a pointer to the initial element of a character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first. To do what you want, read the characters yourself directly from stdin using read(), getc(), or fgets().
FASM IRC Bot Prefix
I've been trying to learn how to create an IRC bot in assembler from some old sources. Everything is going fine with my learning except for a prefix problem. The prefix for the bot is: CommandPrefix equ "^^" And the length of the prefix is added with: add eax, 2d I want to change the prefix to just "^", but I am having trouble with figuring out what "add eax" should be changed too for it to work. Or even if that is the best way to do it. Any help with this would be appreciated. Here is what the original code looks like to get some idea: include "win32ax.inc" entry Bot CommandPrefix equ "^^" section '.code' code readable executable Bot: invoke WSAStartup,0101h,WSAData cmp eax, 0 jne Exit invoke socket,AF_INET,SOCK_STREAM,0 cmp eax, -1 je Exit mov dword [SocketDesc], eax invoke inet_addr,IRCServer mov dword [SockAddr_IP], eax invoke htons,IRCPort mov word [SockAddr_Port], ax invoke connect,dword [SocketDesc],SockAddr,16d cmp eax, 0 jne Exit call GenerateNickname invoke lstrcpy,SendBuffer,"NICK " invoke lstrcat,SendBuffer,Nickname call SendLine invoke lstrcpy,SendBuffer,"USER " invoke lstrcat,SendBuffer,Nickname invoke lstrcat,SendBuffer," 8 * :" invoke lstrcat,SendBuffer,Nickname call SendLine GetMotd: call RecvLine call HandlePing mov ecx, 0 IsMotd: cmp dword [ReturnBuffer + ecx], "MOTD" je HaveMotd cmp byte [ReturnBuffer + ecx], 0d je GetMotd inc ecx jmp IsMotd HaveMotd: invoke lstrcpy,SendBuffer,"JOIN " invoke lstrcat,SendBuffer,Channel invoke lstrcat,SendBuffer," " call SendLine RecvCommand: call RecvLine call HandlePing mov ecx, 0 IsCommand: cmp word [ReturnBuffer + ecx], CommandPrefix je HaveCommand cmp byte [ReturnBuffer + ecx], 0 je RecvCommand inc ecx jmp IsCommand HaveCommand: mov ebx, ReturnBuffer add ebx, ecx add ebx, 2d ;add length of command prefix invoke lstrcpy,CommandBuffer,ebx call ExecuteCommand jmp RecvCommand
C Code NOP confusion
This file is in AT&T syntax - see http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm and http://en.wikipedia.org/wiki/X86_assembly_language#Syntax. Both gdb and objdump produce AT&T syntax by default. MOV $27163,%ebx MOV $13156,%eax MOV $25880,%ecx CMP %eax,%ebx JL L1 JMP L2 L1: IMUL %eax,%ebx ADD %eax,%ebx MOV %ebx,%eax SUB %ecx,%eax JMP L3 L2: IMUL %eax,%ebx SUB %eax,%ebx MOV %ebx,%eax ADD %ecx,%eax L3: NOP What is the value of %eax when the last instruction NOP runs?
The answer is "%933%". (no quotes)
Emacs weirdness when trying to comment in Assembly
Suppose I have a block of code like so: ;; outut mov eax, 4 mov ebx, 1 ; stdout mov ecx, [ans] ; move biggest element to accumulator add ecx, 30h ; convert to ascii representation mov [buff], ecx ; move to memory mov ecx, buff ; put pointer in ecx for printing mov edx, 4 ; size, 4 bytes int 80h ; system call. When I try to put a comment in the front to comment out a line: ;; outut ;mov eax, 4 mov ebx, 1 ; stdout mov ecx, [ans] ; move biggest element to accumulator add ecx, 30h ; convert to ascii representation mov [buff], ecx ; move to memory mov ecx, buff ; put pointer in ecx for printing mov edx, 4 ; size, 4 bytes int 80h ; system call. Instead of appearing there where I want it to go, it jumps to here: ;; outut mov eax, 4 ; mov ebx, 1 ; stdout mov ecx, [ans] ; move biggest element to accumulator add ecx, 30h ; convert to ascii representation mov [buff], ecx ; move to memory mov ecx, buff ; put pointer in ecx for printing mov edx, 4 ; size, 4 bytes int 80h ; system call. And no matter what I do, I physically cannot comment out anything. How can I fix this? It don't remember it always doing this, so i feel like I must have hit some combination of keys and it just happens.
; is bound to asm-comment in assembly mode. You can either do a quoted insert with C-q ; on a case-by-case basis, or remove the binding and just use M-; (comment-dwim) for fancier commenting. If you want to do the latter, set ";" locally to do a self-insert command: (defun my-hook () (local-set-key ";" 'self-insert-command)) (add-hook 'asm-mode-hook 'my-hook)