Wednesday, September 3, 2008

The Chrome experience...

In continuation with my previous article I finally managed to download Chrome and start using it today.
Here is what my first experience with it was ...

First off, I would like to say that sadly I'm still using Firefox to post this, keep reading to see why...

Seeing yesterday's screen shots of the browser made it look kind of simple and plain, but after having used it for some time now I'm really enjoying the amount of screen real-estate that Chrome offers, and the separate URL bar for each tab isn't really a big deal at all, you get used it right away.
Google's done away with the title & Staus bar's and instead the topmost part of the window is the tab itself which looks kinda cool.

The next change you can feel is the speed at which it renders pages. It's blazing fast for the pages it can render (and yeah the separate process per tab is quite true :) you can see that in the TaskManager). The Chrome Task Manager is another great feature that shows you CPU, Network and Memory usage (there is also a "Stats for Nerds" that shows a lot more detail).

Ok, so that was the good part, now for the not so good part...

I wasn't able to open several sites a few of which are Gmail, Google Docs, Blogger (actually pretty much any site that uses my Google id to authenticate), a few bank website's and several pages in my intranet (yeah yeah I know it's beta but still I'd expected at least an error to show up not a blank page).
With Gmail and the Google Docs, I was able to get the login screen initially, but nothing after that and the funny thing is trying to open a new window now does not even give me the login screen (maybe it thinks I still logged in and is unable to display that?). I was using Chrome from behind a proxy that uses proxy server scripts, but I don't think the folks at Goog would have forgotten to test for something like that. From the Chromium bug submission list, I see that this is a problem faced by many other users behind proxy servers and I'm hoping they resolve it soon.

RSS feeds also do not seem to be supported as yet :(, which definitely is something that any self-respecting browser in this age should support, and kinds of make me wonder why Goog was rushing to launch Chrome so early (maybe IE 8's recent launch has something to do with this?).

An other point to be noted, is that you need to have a moderately good system to really use Chrome, a 1 GHz machine I have (!!) simply started crawling when I tried it out.

Anyway overall I did enjoy using Chrome but using it really makes you aware that it is still Beta, and I'm really hoping that changes soon...

Tuesday, September 2, 2008

Google Launching Chrome beta soon....

Google is launching its own web browser named "Chrome". There is a press conference scheduled on Sep 2nd, 11 AM (Pacific Time).

Here's the google-blog page link of the new browser. Their also using quite a novel approach to market the browser initially. Using a comic strip approach for this (can be read here). You should really go through the comic, its quite interesting :).

The launch of this new browser sounds quite exciting as they are using several ideas which seem to be taking the world towards "cloud computing" (which is only logical from their point of view) and blurring the line between browser and OS.

With this they are also now directly challenging M$ IE (version 8 beta 2 was just released a week ago).

The promises of Chrome are,
On the surface,
  • Clean and fast

Under the hood,
  • Each tab is separate process running in a "sandbox" (preventing crashes in one affecting another).
  • A more powerful javascript engine called V8.
  • Better pop-up blocking (sounds promising).
  • Move a tab from one window to another (sounds cool).
  • Built-in Google Gears for web dever's.
  • It's open source.

The only problems I foresee (before actually using the browser) are,
  • Having individual URL boxes for each tab - I guess this is easier from a developer standpoint, as each tab is a separate process now (but Goog seems to be marketing it as a feature :))
  • The "Default" page would have your top nine most frequently visited pages, which may not be what everyone really wants to see when you open your browser.
  • Would it's system requirements be high (Leaning towards multi-core?)

So I guess now we'll have to wait and see how good the browser really turns out to be (it's not yet available for download). Also Chrome would be available only for Windows initially. Linux and Mac users have to wait for now. :(.

Well it's been several hours since I posted the article and the wait is killing me ... :)

Saturday, May 24, 2008

My good ol' FAT12 bootloader

This was the first ever (and the only one to date) ASM program I wrote back in college, that is worth mentioning about. It basically searches a FAT 12 floppy disk for the location of a file named 'BOOT2.BIN' (which is the secondary stage bootloader) and loads it to the real mode address 0x0:0x8000
Feel free to use it (it's a good start to learning how a bootloader works) if you wish. Would be nice if you give the author some credit for this work though if you use it. :)

Here is the algorithm that the code corresponds to,
* Setup Registers and Variables needed (initialization)
* Calculate the start of Root Directory
* Calculate the start of Data Area
* Read the Root Directory contents to 0x0:0x700
* Search the entries one by one for the specified file
* If found read in the FAT to 0x0:0x2500 and start following the FAT chain till EOF
* Read in the file from Disk sectors to address 0x0:0x8000
* Transfer control to the address 0x0:0x8000


Pretty simple isn't it? Here's the same thing in ASM (I had used the NASM assembler back then),

Please use a fixed size font such as Courier New for best viewing
;/*/////////////////////////////////////////////////////////////////////////////////////*\
;// THIS IS A PRIMARY BOOT LOADER FOR A FAT 12 FLOPPY - Anselm Joseph Meyn //
;// //
;// boot sector code loaded to 0x7C00:start (512 bytes by the BIOS) //
;// The FAT12 Root Directory loaded at 0x0:0x700 - 0x0:0x2300 (14 sectors) //
;// The FAT is next loaded at location 0x0:0x2500 - 0x0:0x4b00 (19 sectors) //
;// The Secondary file is loaded in at 0x0:0x8000 //
;// Stack is from 0x0 - 0x700 (SP=0x700, SS=0x0) //
;// //
;// The NAME of the secondary stage is BOOT2.BIN (this may be changed if you wish) //
;// Last Modified :- February 26,2004 [Version 1.1] //
;\*/////////////////////////////////////////////////////////////////////////////////////*/


[BITS 16]
%define RD_BUFF 0x700
%define FAT_BUFF 0x2500
%define FILE_BUFF 0x8000
[ORG 0]
entry:
jmp short begin
nop
LABEL DB 'FAT12FLP'
BYTES_PER_SECT DW 0200h
SECTS_PER_CLUST DB 01h
SECTS_IN_BOOT DW 01h
FAT_COPIES DB 02h
DIR_ENTRIES DW 0e0h
SECTORS DW 0b40h
DISK_TYPE DB 0F0h
SECTS_PER_FAT DW 09h
SECTS_PER_TRK DW 012h
HEADS DW 02h
HIDDEN_SECTS DD 0h

HUGE_SECTS DD 0h
DRIVE_NO DB 0h
RESERVED DB 0h
BOOT_SIGN DB 29h
VOL_ID DD 00007c00h
VOL_LABEL DB 'ANSELM MEYN'
FS_TYPE DB 'FAT12 '

begin:
jmp 0x07c0:.start
.start:
cli ; disable interrupts
mov ax,cs ; initialize all the necessary
mov ds,ax ; registers DS==CS
mov ax,0
mov es,ax ; ES=SS=0
mov ss,ax
mov sp,0x700 ; Stack pointer at 0x700
mov [DRIVE_NO],dl ; save DRIVE_NO here
sti ; enable interrupts
;________________________________________________________________________________
; Calculate the start of Root Directory and save in AX +
;-------------------------------------------------------------------------------+

mov al,[FAT_COPIES] ; no of FAT copies in al
mov bx,[SECTS_PER_FAT] ; no of sectors per FAT in BX
mul bx ; multiply it
add ax,[SECTS_IN_BOOT] ; add sectors in boot
add ax,word [HIDDEN_SECTS] ; add hidden sectors
; AX = Start of Root Dir(19 here)
;________________________________________________________________________________

;________________________________________________________________________________
; Calculate the start of Data Area and save it in a variable +
;-------------------------------------------------------------------------------+

mov dx,[DIR_ENTRIES] ; no. of Root Dir Entries in AX
shl dx,5 ; Multiply by 32(bytes per entry)
add dx,[BYTES_PER_SECT] ; add bytes per sector to it(bootsector)
dec dx ; decrement by one for calculation
shr dx,9 ; divide by 512(bytes_per_sect)
push dx ; This is the no. of RD sectors
; to read in. DX=14
add dx,ax ; Add RD Start to it to get DA Start
mov [SECTS_B4_DA],dx ; save this value in a variable
;________________________________________________________________________________

;________________________________________________________________________________
; Now to read the Root Directory at 0x0:RD_BUFF +
; Reads the entries at ES:BX +
;-------------------------------------------------------------------------------+

call trans_address ; AX translated to physical address
mov bx,RD_BUFF ; BUFFER to read the ROOT_DIR
pop ax ; sectors to read in
call disk_read ; read the disk sector
;________________________________________________________________________________

;________________________________________________________________________________
; Now the search for internal files begins +
; Called after reading the directory entries +
; this searches first 16 entries for the given filename +
; The Root Directory entry is in DS:SI +
; and the filename in ES:DI +
;-------------------------------------------------------------------------------+

mov dx,[DIR_ENTRIES] ; move the no of entries into DX
mov bx,RD_BUFF ; ROOT DIRECTORY Buffer in BX
filsrch:
cld
mov si,file ; file name
mov di,bx ; move entry BASE+BX to DI
mov cx,0bh ; 11 bytes to compare
repe cmpsb ; check for existence of file
je short found ; if the file is found goto FOUND
;
add bx,20h ; increment BX by 32 bytes(next entry)
dec dx ; else decrement entry count
jnz short filsrch ; and search for the next file
mov si,finderr ; Finally display file error
call print ;
jmp error ; if not found
;________________________________________________________________________________

found:
;________________________________________________________________________________
; If the file is found then +
; address of file directory entry is in BX +
; Read in the FAT now +
;-------------------------------------------------------------------------------+

mov dx,[es:bx+1ah] ; get start cluster of file in DX
mov ax,[SECTS_IN_BOOT] ; start of FAT in AX
push dx ; save entry cluster value
call trans_address ; translate address to physical
mov bx,FAT_BUFF ; and buffer to store FAT table in BX
mov ax,[SECTS_PER_FAT] ; sectors to read
call disk_read ; Read the disk now to get FAT in memory
pop ax ; entry cluster value in AX
;________________________________________________________________________________

;________________________________________________________________________________
; Search and read of the File clusters +
; Here AX=ENTRY CLUSTER, BX=FAT_BUFF,CX=?,DX=? +
;--------------------------------------------------------------------------------+

mov bx,FILE_BUFF ; BUFFER to read in the file
sub bx,200h ;
jmp short chk ; check the entry cluster
fat_cont:
mov ax,dx ; DX=AX=cluster value
add ax,ax ; AX multiplied by 2
add ax,dx ; multiplied by 3(add 3 times)
clc ; clear out carry flag
rcr ax,1 ; divide by 2 (multiplying by 1.5 actually)
pushf ; save flags
push bx ; and BX reg value
mov bx,FAT_BUFF ; get the FAT
add bx,ax ; entry values
mov ax,[es:bx] ; in AX
pop bx ; retrieve BX value
popf ; and flags
jc short .rl ; is result not an integer
;integer part
and ax,0x0fff ; else AND with 0x0fff
jmp short chk ; continue checking
.rl: ; real value part
shr ax,4 ; if odd right shift by 4 bits
chk:
push ax ; save AX value
cmp ax,0x0ff8 ; is this the last cluster
jge short quit ; yes then exit
dec ax ; else subtract 2
dec ax ; from the FAT entry
add ax,[SECTS_B4_DA] ; AX = sector to read data from
call trans_address ; Get physical address
add bx,200h ; add offset 512 bytes for next sector to BX
mov al,01 ; no. sectors to read
call disk_read ; Read the sector
pop dx ; restore DX value
jmp short fat_cont ; continue the fat loop for next sector
;________________________________________________________________________________
quit:
mov dl,[DRIVE_NO] ; save some info for the secondary
mov dh,[SECTS_B4_DA]
mov bl,[SECTS_PER_TRK]
mov bh,[HEADS]
push dx
push bx
mov si,msg_success
call print

jmp 0000:FILE_BUFF ; jump to secondary loader code

;
; COMMON ROUTINES USED, BEGIN FROM HERE
;

error:
; ______________________________________________________________________________
;/
This is called on any error it displays an error message and \
;
asks the user to press any key for reboot *
;
Input:- the specific String in SI reg *
;
clobbers SI Reboots at the end *
;-------------------------------------------------------------------------------*
mov si,errmsg
; display the
call print
; error message
mov ah,0
int 16h
; wait for key press
int 19h
; reboot
;\______________________________________________________________________________/

print:
; ______________________________________________________________________________
;/ Print Function for NULL terminated Strings \
; the NULL terminated string must be present in SI *
; Registers Affected:- AX,BX(popped back) *
;-------------------------------------------------------------------------------*

push ax ; save AX and BX
push bx ; registers
ploop:
cld
lodsb ; AL = [DS:SI]
or al, al ; Set zero flag if al=0
jz short pstop ; jump to stop if zero flag is set
mov ah, 0eh ; video function 0Eh (print char)
mov bx, 0007h ; color
int 10h ; interrupt 10h for screen display
jmp short ploop ; keep printing
pstop:
pop bx ; retrieve BX and
pop ax ; AX registers
retn ; end print
;\______________________________________________________________________________/

disk_read:
; ______________________________________________________________________________
;/ Disk Read Routine using int13h, the registers must be set up already \
; Input:- ES:BX=Dest address,AL=no. of continuos sectors, CX,DX
; Output:- CF=success/failure,AL=sectors read,AH=stat code
; Re-tries 3 times for read
; Registers Affected:-AH=02,all
;-------------------------------------------------------------------------------*

mov bp,3 ; counter
mov dl,[DRIVE_NO] ; move drive no to dl
.rtry: ;
mov ah,0x0 ; reset the drive
int 13h ;
jc short .rtry ; if error retry
dec bp ; decrement counter
jz .err ; if it is not zero retry
mov ah,0x2 ; disk read function
int 13h ; no then read it
jc short .rtry ; if no read errror then
retn ; end disk_read
.err:
mov si,readerr ; otherwise display an
call print ; error message
jmp error ; and reboot
;\______________________________________________________________________________/

trans_address:
; ______________________________________________________________________________
;/ Translates Logical sector in AX to Physical sector,head,cylinder \
; Input:- the LBA address in the AX reg
; Output:- cl=sector,ch=cylinder,dh=head
; Formula:-
; HPC = Number of heads/cylinder
; SPT = sectors/track
; Sector = (LBA mod SPT) + 1
; Head = (LBA / SPT) mod HPC
; Cylinder = (LBA / SPT) / HPC
; Registers Affected:- AX, CX, DX
;-------------------------------------------------------------------------------*

xor dx,dx ; clear out DX reg
div word [SECTS_PER_TRK] ; divide AX by SPT
inc dl ; increment dl to get sector address
mov cl,dl ; get sector value
xor dx,dx ; clear DX reg
div word [HEADS] ;
mov ch,al ; get cylinder value
mov dh,dl ; get head value
retn ; all values obtained now
;\______________________________________________________________________________/

file db 'BOOT2 BIN'
readerr db CR,LF,'I/O Error',0
finderr db CR,LF,'File Missing',0
errmsg db CR,LF,'Press key to reboot...',0
msg_success db CR,LF,'Bootstrap Complete',0
SECTS_B4_DA dw 0

size equ $-entry
%if size+2>512
%error "code greater than 512 bytes"
%endif
times (510-size) db 0
dw 0xaa55

CR equ 0x0d
LF equ 0x0a

Monday, May 5, 2008

C++ const pointer declaration

Came across this interesting issue with the use of C++ const pointers, that help explain the effects of using the const keyword, incorrectly with pointers.
Here's the minimum code needed to understand this,

//File: a.h
#ifndef __MY_HEADER__
#define __MY_HEADER__
const char* ptr = "A String";
#endif


//File: a.cpp
#include "a.h"
int main()
{
return 0;
}


//File: b.cpp
#include "a.h"

Compiling the above code with g++ (used version 2.8.1) gave the following error,
/var/tmp/ccp3aGWX2.o(.data+0x0): multiple definition of `ptr'
/var/tmp/ccp3aGWX1.o(.data+0x0): first defined here


At first glance this seemed like a weird error from the linker. After all this was just a constant string in the header file (or wasn't it?). But the linker was indicating that the variable was in the .data section of the object file, which was not what was wanted or expected. And on replacing this pointer with an array it worked fine.

To confirm I objdump'ed the files.
The one with the 'const char *' showed the following,
a.o: file format elf32-sparcb.o: file format elf32-sparc
SYMBOL TABLE:

00000000 l df *ABS* 00000000 a.cpp
00000000 l d .text 00000000
00000000 l d .data 00000000
00000000 l d .bss 00000000
00000000 l .text 00000000 gcc2_compiled.
00000000 l d .rodata 00000000
00000000 l d .eh_frame 00000000
00000000 l .eh_frame 00000000 __FRAME_BEGIN__
00000000 l *ABS* 00000000 *ABS*
00000000 l d .comment 00000000
00000000 g O .data 00000004 ptr
00000000 g F .text 00000024 main
SYMBOL TABLE:

00000000 l df *ABS* 00000000 b.cpp
00000000 l d .text 00000000
00000000 l d .data 00000000
00000000 l d .bss 00000000
00000000 l .text 00000000 gcc2_compiled.
00000000 l d .rodata 00000000
00000000 l d .eh_frame 00000000
00000000 l .eh_frame 00000000 __FRAME_BEGIN__
00000000 l d .comment 00000000
00000000 g O .data 00000004 ptr

While the objdump of the files with the const char array showed this,
a.o: file format elf32-sparcb.o: file format elf32-sparc
SYMBOL TABLE:

00000000 l df *ABS* 00000000 a.cpp
00000000 l d .text 00000000
00000000 l d .data 00000000
00000000 l d .bss 00000000
00000000 l .text 00000000 gcc2_compiled.
00000000 l d .rodata 00000000
00000000 l O .rodata 00000009 ptr
00000000 l d .eh_frame 00000000
00000000 l .eh_frame 00000000 __FRAME_BEGIN__
00000000 l *ABS* 00000000 *ABS*
00000000 l d .comment 00000000
00000000 g F .text 00000024 main
SYMBOL TABLE:

00000000 l df *ABS* 00000000 b.cpp
00000000 l d .text 00000000
00000000 l d .data 00000000
00000000 l d .bss 00000000
00000000 l .text 00000000 gcc2_compiled.
00000000 l d .rodata 00000000
00000000 l O .rodata 00000009 ptr
00000000 l d .eh_frame 00000000
00000000 l .eh_frame 00000000 __FRAME_BEGIN__
00000000 l d .comment 00000000

This showed that const char *ptr = "A string" was clearly not a const to the compiler (it was being put into the .data section and not the .rodata), leading me to look more closely at what I was declaring. What I had was a variable pointer to a const string which was causing the linker to complain.

The const declaration in C++ applies to whatever is on its immediate left (except when there is nothing to its left, in which case it then applies to whatever is to its immediate right). So in the above declaration the const applied to the char not to the '*'(pointer) and thus declaring a string that cannot be modified ("A String"), with a pointer (ptr) pointing to it (duh!) that could potentially be made to point to something else.

This left the gcc linker (ld) uncomfortable and caused it to complain (with diab however it just issued a warning and continued to link).

Changing the declaration to
const char * const ptr = "A string";
resolved the issue and thought it taught me to be more careful with my declaration of const's, I think in this case at least it would have been better to have used the string type instead. :)

Wednesday, January 9, 2008

In the beginning

Had wanted to start blogging quite some time back (3 years ago actually) but didn't find a compelling reason to do so (not that I have one now).
So I've started this in the hope that at least now I will try to do something other than the same drab stuff I do everyday.

Well here's wishing myself luck to do that from now on at least :)