4-TEL
Vào tháng 10 năm 1976, sau khi bị OMC sa thải, tôi trở lại một bộ phận khác của Teradyne – một bộ phận mà tôi sẽ gắn bó trong 12 năm. Sản phẩm tôi làm có tên là 4-TEL. Mục đích của nó là để kiểm tra mọi đường dây điện thoại trong một khu vực dịch vụ điện thoại vào hàng đêm và đưa ra một báo cáo về tất cả các đường dây cần sửa chữa. Nó cũng cho phép nhân viên kiểm tra điện thoại kiểm tra chi tiết các đường dây điện thoại cụ thể.
Hệ thống này bắt đầu ra đời với kiểu kiến trúc tương tự như hệ thống cắt bằng tia Laser. Nó là một ứng dụng nguyên khối được viết bằng hợp ngữ mà không có bất kỳ ranh giới nào đáng kể. Nhưng vào thời điểm tôi gia nhập công ty, điều đó sắp sửa thay đổi.
Hệ thống được sử dụng bởi những người kiểm tra đặt tại một trung tâm dịch vụ (Service Center – SC). Một trung tâm dịch vụ bao gồm nhiều văn phòng trung tâm (Central Office – CO), mỗi văn phòng có thể xử lý tới 10.000 đường dây điện thoại. Phần cứng đo lường và quay số phải được đặt bên trong CO. Vì vậy, đó là nơi đặt các máy tính M365. Chúng tôi gọi những chiếc máy tính đó là máy kiểm tra đường truyền văn phòng trung tâm (Central Office Line Tester – COLT). Một chiếc M365 khác đã được đặt tại SC; nó được gọi là máy tính vùng dịch vụ (Service Area Computer – SAC). SAC có một số modem mà nó có thể sử dụng để quay số COLT và giao tiếp với tốc độ 300-baud (30-cps).
Lúc đầu, các máy tính COLT làm mọi thứ, bao gồm tất cả các giao tiếp bảng điều khiển, menu và báo cáo. SAC chỉ là một bộ ghép kênh đơn giản lấy đầu ra từ các COLT và đưa nó lên màn hình.
Vấn đề với cách thiết lập này là tốc độ 30-cps thực sự chậm. Những người kiểm tra không thích xem các ký tự xuất hiện rề rề trên màn hình, đặc biệt là vì họ chỉ quan tâm đến một vài bit dữ liệu quan trọng. Ngoài ra, trong những ngày đó, bộ nhớ nhân trong M365 rất đắt tiền và chương trình này thì khá lớn.
Giải pháp được đưa ra là tách phần phần mềm quay số và đo đường khỏi phần phân tích kết quả và in báo cáo. Cái sau sẽ được chuyển vào SAC, và cái trước sẽ ở lại COLTs. Điều này sẽ cho phép COLT trở thành một chiếc máy nhỏ hơn, với ít bộ nhớ hơn nhiều và sẽ tăng tốc đáng kể phản hồi tại thiết bị đầu cuối, vì các báo cáo sẽ được tạo trong SAC.
Kết quả này là một thành công xuất sắc. Cập nhật màn hình rất nhanh (sau khi COLT thích hợp đã được quay số) và bộ nhớ của các COLT đã giảm đi rất nhiều.
Ranh giới rất sạch và được tách biệt rõ ràng. Các gói dữ liệu rất ngắn đã được trao đổi giữa SAC và COLT. Các gói này là một dạng DSL rất đơn giản, đại diện cho các lệnh như “DIAL XXXX” hoặc “MEASURE.”
M365 được nạp từ các cuộn băng từ. Những ổ băng từ đó rất đắt tiền và hoạt động không đáng tin cậy lắm – đặc biệt là trong môi trường công nghiệp của văn phòng trung tâm điện thoại. Ngoài ra, M365 là một chiếc máy đắt tiền so với phần còn lại của các thiết bị điện tử trong COLT. Vì vậy, chúng tôi bắt tay vào một dự án thay thế M365 bằng một máy vi tính dựa trên bộ vi xử lý 8085.
Máy tính mới này bao gồm một bảng mạch để lắp vi xử lý 8085, một bảng mạch RAM chứa 32K RAM và ba bảng mạch ROM chứa 12K bộ nhớ chỉ đọc. Tất cả các bo mạch này đều nằm gọn trong cùng một bộ vỏ với phần cứng đo lường, do đó loại bỏ được lớp vỏ ngoài cồng kềnh đã chứa M365.
Các bảng ROM chứa 12 chip Intel 2708 EPROM (Erasable Programmable Read-Only Memory – Bộ nhớ chỉ đọc lập trình có thể xóa)[1]. Hình A.8 cho một ví dụ về con chip như vậy. Chúng tôi đã nạp những con chip đó bằng phần mềm bằng cách chèn chúng vào các thiết bị đặc biệt gọi là đầu ghi PROM được điều khiển bởi môi trường phát triển của chúng tôi. Những con chip này có thể được xóa bằng cách phơi chúng dưới tia cực tím cường độ cao[2].
Bạn tôi CK và tôi đã dịch chương trình hợp ngữ M365 cho COLT sang hợp ngữ của 8085. Bản dịch này được thực hiện bằng tay và chúng tôi mất khoảng 6 tháng. Kết quả cuối cùng là khoảng 30 nghìn dòng code 8085.
Môi trường phát triển của chúng tôi có 64K RAM và không có ROM, vì vậy chúng tôi có thể nhanh chóng tải xuống các file nhị phân đã biên dịch của mình vào RAM và kiểm tra chúng.
Sau khi chương trình hoạt động, chúng tôi chuyển sang sử dụng EPROM. Chúng tôi đã ghi 30 con chip và lắp chúng vào đúng các khe cắm trong ba bảng ROM. Mỗi con chip đều được dán nhãn để chúng tôi có thể biết con chip nào đã đi vào khe nào.
Chương trình 30K là một chương trình nhị phân duy nhất, dài 30K dòng. Để ghi các chip, chúng tôi chỉ cần chia ảnh nhị phân đó thành 30 phần 1K khác nhau và ghi từng phần vào chip được dán nhãn thích hợp.
Điều này hoạt động rất tốt, và chúng tôi bắt đầu sản xuất hàng loạt phần cứng và triển khai hệ thống trên hiện trường.
Nhưng phần mềm thì mềm[3]. Các chức năng thì cần được thêm vào. Các bug thì cần được sửa chữa. Và khi chương trình cài đặt lớn dần, việc cập nhật phần mềm bằng cách ghi 30 con chip mỗi lần cài đặt, ngoài ra còn phải có người xuống tận nơi để thay thế tất cả 30 con chip này tại tất cả các khu vực đã trở thành một cơn ác mộng.
Điều này dẫn tới có thể xảy ra tất cả các loại vấn đề. Đôi khi các chip sẽ bị dán nhãn sai hoặc nhãn bị rơi ra. Đôi khi kỹ sư dịch vụ hiện trường đã nhầm lẫn thay sai chip. Đôi khi kỹ sư dịch vụ hiện trường vô tình làm gãy chân của một trong các chip mới. Kết quả là các kỹ sư hiện trường đã phải mang theo tất cả 30 con chip bổ sung bên mình.
Tại sao chúng tôi phải thay đổi tất cả 30 con chip? Mỗi khi chúng tôi thêm hoặc xóa code khỏi file thực thi 30K của mình, nó sẽ thay đổi địa chỉ mà mỗi lệnh được nạp. Nó cũng thay đổi địa chỉ của các chương trình con và hàm mà chúng tôi đã gọi. Vì vậy, mọi con chip đều bị ảnh hưởng, bất kể sự thay đổi nhỏ đến mức nào.
Một ngày nọ, sếp của tôi đến gặp tôi và yêu cầu tôi giải quyết vấn đề đó. Ông ấy nói rằng chúng tôi cần một cách để thay đổi đối với firmware mà không cần thay thế tất cả 30 con chip mỗi lần. Chúng tôi cùng nhau suy nghĩ về vấn đề này một lúc, và sau đó khởi hành dự án “Vectorization”. Tôi đã mất ba tháng vì nó.
Ý tưởng này rất đơn giản. Chúng tôi chia chương trình 30K thành 32 file nguồn có thể biên dịch độc lập, mỗi file nhỏ hơn 1K. Ở đầu mỗi file nguồn, chúng tôi cho trình biên dịch biết địa chỉ nào để nạp chương trình kết quả (ví dụ: ORG C400 cho con chip sẽ được đưa vào vị trí C4).
Ngoài ra, ở đầu mỗi file nguồn, chúng tôi đã tạo một cấu trúc dữ liệu đơn giản, có kích thước cố định chứa tất cả địa chỉ của tất cả các chương trình con trên chip đó. Cấu trúc dữ liệu này dài 40 byte, vì vậy nó có thể chứa không quá 20 địa chỉ. Điều này có nghĩa là không con chip nào có thể có nhiều hơn 20 chương trình con.
Tiếp theo, chúng tôi tạo một vùng đặc biệt trong RAM được gọi là vectơ. Nó chứa 32 bảng 40 byte – vừa đủ RAM để chứa các con trỏ ở đầu mỗi chip.
Cuối cùng, chúng tôi đã thay đổi tất cả các lệnh gọi đến các chương trình con trên tất cả các chip thành một lệnh gọi gián tiếp thông qua vectơ RAM thích hợp.
Khi bộ vi xử lý của chúng tôi khởi động, nó sẽ quét từng chip và nạp bảng vectơ ở đầu mỗi con chip vào các vectơ RAM. Sau đó, nó sẽ nhảy tới chương trình chính.
Phương án này hoạt động rất tốt. Giờ đây, khi chúng tôi sửa lỗi hoặc thêm một tính năng, chúng tôi có thể chỉ cần biên dịch lại một hoặc hai chip và chỉ gửi những chip đó cho các kỹ sư dịch vụ hiện trường.
Chúng tôi đã làm cho các chip có thể triển khai độc lập. Chúng tôi đã phát minh ra điều phối đa hình. Chúng tôi đã phát minh ra các đối tượng.
Theo nghĩa đen, đây là một kiến trúc plugin. Chúng tôi đã cắm những con chip đó vào. Cuối cùng, chúng tôi đã thiết kế nó để một tính năng có thể được cài đặt vào sản phẩm của chúng tôi bằng cách cắm con chip có tính năng đó vào một trong những ổ cắm chip đang mở. Quá trình điều khiển danh mục sẽ tự động xuất hiện, và việc gắn nó vào ứng dụng chính sẽ tự động xảy ra.
Tất nhiên, vào thời điểm đó, chúng tôi không biết gì về các nguyên tắc hướng đối tượng và chúng tôi cũng không biết gì về việc tách giao diện người dùng khỏi các quy tắc nghiệp vụ. Nhưng những thứ sơ khai đó đã có và chúng hoạt động rất mạnh mẽ.
Một lợi ích phụ không ngờ của phương pháp này là chúng tôi có thể vá firmware thông qua kết nối quay số. Nếu chúng tôi phát hiện thấy lỗi trong firmware, thì chúng tôi có thể quay số thiết bị của mình và sử dụng chương trình giám sát trên bo mạch để thay đổi vectơ RAM cho chương trình con bị lỗi để trỏ đến một bit RAM trống. Sau đó, chúng tôi sẽ nhập chương trình con đã sửa chữa vào vùng RAM đó, bằng cách nhập nó dưới dạng mã máy số hex.
Đây là một lợi ích tuyệt vời cho hoạt động dịch vụ hiện trường của chúng tôi và cho khách hàng của chúng tôi. Nếu họ gặp sự cố, họ không cần chúng tôi gửi chip mới và lên lịch cho cuộc gọi dịch vụ hiện trường khẩn cấp. Hệ thống đó có thể được vá và một con chip mới có thể được cài đặt vào lần bảo trì định kỳ tiếp theo.
Máy tính vùng dịch vụ
Máy tính vùng dịch vụ 4-TEL (Service Area Computer – SAC) dựa trên máy tính mini M365. Hệ thống này giao tiếp với tất cả các COLT ngoài hiện trường, thông qua modem chuyên dụng hoặc quay số. Nó sẽ ra lệnh cho các COLT đó đo đạc đường dây điện thoại, và nhận lại các kết quả thô, và sau đó sẽ thực hiện một phân tích phức tạp về các kết quả đó để xác định và định vị bất kỳ lỗi nào.
Xác định điều phối
Một trong những nền tảng kinh tế cho hệ thống này là dựa vào việc phân bổ các thợ sửa chữa chính xác. Theo quy tắc của hiệp hội, đội sửa chữa được tách ra thành ba loại: văn phòng trung tâm (CO), cáp và drop (thả). Thợ CO khắc phục các sự cố bên trong văn phòng trung tâm. Thợ cáp khắc phục sự cố cáp kết nối từ CO tới khách hàng. Thợ drop khắc phục các sự cố bên trong cơ sở của khách hàng và các đường kết nối cáp bên ngoài với cơ sở đó (“drop”).
Khi một khách hàng phàn nàn về một vấn đề, thì hệ thống của chúng tôi có thể chẩn đoán vấn đề và xác định loại thợ nào cần được cử đi sửa. Điều này tiết kiệm cho các công ty điện thoại rất nhiều tiền bởi vì việc điều phối không đúng nghĩa là khách hàng bị chậm trễ mà thợ thì lãng phí mất chuyến đi.
Phần code để xác định việc điều phối được thiết kế và viết bởi một ai đó rất thông minh, nhưng khả năng giao tiếp lại hết sức tồi tệ. Quá trình viết phần code này đã được mô tả là “Ba tuần nhìn chằm chằm lên trần nhà và hai ngày code tuôn ra từ mọi lỗ thông của cơ thể anh ta – sau đó anh ta nghỉ việc.”
Không ai hiểu nổi phần code này. Mỗi lần chúng tôi cố gắng thêm một chức năng hoặc để sửa một lỗi, thì chúng tôi lại làm hỏng nó theo cách nào đó. Và bởi vì phần code này là một trong những lợi ích kinh tế chính của hệ thống của chúng tôi, nên mọi lỗi mới đều khiến công ty vô cùng khốn đốn.
Cuối cùng, quản lý của chúng tôi chỉ đơn giản là yêu cầu chúng tôi khóa phần code đó lại và không bao giờ sửa đổi nó. Phần code đó chính thức trở nên cho đóng cứng.
Trải nghiệm này khiến tôi ấn tượng về giá trị của code tốt, tinh gọn.
Kiến trúc
Hệ thống này được viết vào năm 1976 bằng trình biên dịch hợp ngữ M365. Đó là một chương trình đơn, nguyên khối với khoảng 60.000 dòng code. Hệ điều hành này là một bộ chuyển đổi tác vụ tự phát triển dựa trên cơ chế polling. Chúng tôi gọi nó là MPS cho hệ thống đa xử lý. Máy tính M365 không có stack tích hợp, vì vậy các biến của một nhiệm vụ cụ thể được lưu giữ trong một vùng đặc biệt của bộ nhớ và được hoán đổi mỗi khi chuyển đổi ngữ cảnh. Các biến chia sẻ thì được quản lý bằng khóa và semaphore. Các vấn đề về reentrancy và race condition là những vấn đề thường gặp khi đó.
Hệ thống này không có sự tách biệt logic điều khiển thiết bị hoặc logic UI khỏi các quy tắc nghiệp vụ của hệ thống. Ví dụ: mã điều khiển modem có thể được tìm thấy trong phần lớn các quy tắc nghiệp vụ và mãUI. Không hề có nỗ lực nào để tập hợp nó vào một module hoặc một interface trừu tượng. Các modem được điều khiển, ở cấp độ bit, bằng mã nằm rải rác khắp nơi trong hệ thống.
Với UI thiết bị đầu cuối thì cũng giống như vậy. Các thông báo và mã điều khiển định dạng không được tách biệt. Chúng bao phủ rất xa và rộng khắp trong toàn bộ code base 60K dòng này.
Các module modem chúng tôi đang sử dụng được thiết kế để gắn trên bo mạch PC. Chúng tôi đã mua các bộ modem đó từ một bên thứ ba và tích hợp chúng với mạch điện khác vào một bảng phù hợp với bảng mạch chủ tùy chỉnh của chúng tôi. Những bộ modem này rất đắt tiền. Vì vậy, sau một vài năm, chúng tôi quyết định thiết kế modem của riêng mình. Chúng tôi, trong nhóm phần mềm, đã yêu cầu nhà thiết kế phần cứng sử dụng các định dạng bit tương tự để điều khiển modem mới. Chúng tôi giải thích rằng mã điều khiển modem đã bị lan tràn khắp nơi và hệ thống của chúng tôi sẽ phải xử lý cả hai loại modem trong tương lai. Vì vậy, chúng tôi đã cầu xin và tán tỉnh, “Xin hãy làm cho modem mới giống như modem cũ theo quan điểm kiểm soát phần mềm.”
Nhưng khi chúng tôi nhận modem mới, cấu trúc điều khiển lại hoàn toàn khác. Nó không chỉ khác một chút. Nó hoàn toàn, và hoàn toàn khác.
Cảm ơn, kỹ sư phần cứng.
Chúng ta phải làm gì đây? Chúng tôi không chỉ đơn giản là thay thế tất cả các modem cũ bằng các modem mới. Thay vào đó, chúng tôi đã trộn modem cũ và mới trong hệ thống của mình. Phần mềm yêu cầu phải xử lý cả hai loại modem cùng một lúc. Chúng tôi đã tiêu tùng khi bị mã điều khiển modem với các cờ và các trường hợp đặc biệt vây quanh mọi nơi phải không? Phải có tới hàng trăm nơi như vậy!
Cuối cùng, chúng tôi đã chọn một giải pháp thậm chí còn tồi tệ hơn.
Một chương trình con cụ thể đã ghi dữ liệu vào bus giao tiếp nối tiếp được sử dụng để điều khiển tất cả các thiết bị của chúng tôi, bao gồm cả modem của chúng tôi. Chúng tôi đã sửa đổi chương trình con đó để nhận dạng các mẫu bit dành riêng cho modem cũ và chuyển chúng thành các mẫu bit mà modem mới cần.
Điều này không đơn giản. Các lệnh tới modem bao gồm các chuỗi ghi vào các địa chỉ IO khác nhau trên bus nối tiếp. Kiểu hack của chúng tôi phải biên dịch các lệnh này theo trình tự và dịch chúng thành một trình tự khác bằng cách sử dụng các địa chỉ IO, định thời gian và vị trí bit khác nhau.
Chúng tôi đã làm cho nó hoạt động, nhưng đó là vụ hack tồi tệ nhất có thể tưởng tượng được. Chính vì sự thất bại này mà tôi đã học được giá trị của việc tách biệt phần cứng khỏi các quy tắc nghiệp vụ và của các interface trừu tượng.
Cuộc thiết kế lại vĩ đại trên trời
Vào thời điểm những năm 1980, ý tưởng sản xuất máy tính mini của riêng bạn và kiến trúc máy tính của riêng bạn bắt đầu không còn hợp thời. Có rất nhiều máy vi tính trên thị trường, và việc sử dụng chúng thì rẻ hơn và tiêu chuẩn hơn so với việc tiếp tục dựa vào các kiến trúc máy tính tự phát triển từ cuối những năm 1960. Điều đó, cộng với kiến trúc khủng khiếp của phần mềm SAC, đã khiến ban quản lý kỹ thuật của chúng tôi bắt đầu tái cấu trúc toàn bộ hệ thống SAC.
Hệ thống mới sẽ được viết bằng C sử dụng UNIX O/S trên đĩa cứng, chạy trên máy vi tính Intel 8086. Các chuyên gia phần cứng của chúng tôi đã bắt đầu làm việc trên phần cứng của chiếc máy tính mới và một nhóm các lập trình viên được chọn lọc, “Tiger Team,” đã được giao nhiệm vụ viết lại.
Tôi sẽ không làm bạn buồn chán với các chi tiết về thất bại ban đầu. Chỉ cần nói rằng Tiger Team lần đầu tiên đã thất bại hoàn toàn sau khi đốt cháy hai hoặc ba năm nhân lực cho một dự án phần mềm không bao giờ mang lại điều gì.
Một hoặc hai năm sau, có thể là năm 1982, quá trình này lại được bắt đầu lại. Mục tiêu là thiết kế lại toàn bộ và hoàn chỉnh SAC bằng C và UNIX trên phần cứng 80286 được thiết kế mới, ấn tượng, mạnh mẽ của chúng tôi. Chúng tôi gọi chiếc máy tính đó là “Deep Thought”.
Phải mất nhiều năm, sau đó nhiều năm, và thậm chí nhiều năm nữa. Tôi không biết khi nào SAC dựa trên UNIX cuối cùng mới được triển khai; tôi nhớ rằng tôi đã rời công ty vào thời điểm đó (1988). Quả thực là tôi không chắc nó đã từng được triển khai hay chưa.
Tại sao lại chậm trễ như vậy? Nói ngắn gọn, đội ngũ thiết kế lại sẽ rất khó bắt kịp với đội ngũ lập trình viên đông đảo đang tích cực bảo trì hệ thống cũ. Đây chỉ là một ví dụ về những khó khăn mà họ gặp phải.
Châu Âu
Cùng thời điểm SAC được thiết kế lại bằng ngôn ngữ C, công ty cũng bắt đầu mở rộng bán hàng sang châu Âu. Họ không thể đợi phần mềm được thiết kế lại hoàn thiện, nên dĩ nhiên, họ đã triển khai các hệ thống M365 cũ vào châu Âu.
Vấn đề là hệ thống điện thoại ở châu Âu rất khác với hệ thống điện thoại ở Hoa Kỳ. Việc tổ chức thủ công và các bộ máy hành chính cũng khác nhau. Vì vậy, một trong những lập trình viên giỏi nhất của chúng tôi đã được cử sang Anh Quốc để lãnh đạo một nhóm các lập trình viên của Anh Quốc nhằm sửa đổi phần mềm SAC để giải quyết tất cả các vấn đề châu Âu này.
Tất nhiên, không có nỗ lực nghiêm túc nào được thực hiện để tích hợp những thay đổi này vào phần mềm của Hoa Kỳ. Điều này đã xảy ra rất lâu trước khi hệ thống mạng internet giúp cho việc truyền các code base lớn qua đại dương trở nên khả thi. Các lập trình viên Anh Quốc này chỉ cần dựa trên code của Hoa Kỳ và sửa đổi nó nếu cần.
Điều này tất nhiên gây ra khó khăn. Các lỗi được tìm thấy ở cả hai bên bờ Đại Tây Dương cần được sửa chữa ở phía bên kia. Nhưng các module đã thay đổi đáng kể, vì vậy rất khó xác định liệu bản sửa lỗi được thực hiện tại Hoa Kỳ có hoạt động ở Anh Quốc hay không.
Sau một vài năm không đâu vào đâu, một đường dây tốc độ cao kết nối các văn phòng giữa Hoa Kỳ và Anh Quốc được lắp đặt, một nỗ lực nghiêm túc đã được thực hiện để tích hợp hai code base này lại với nhau, làm cho sự khác biệt trở thành vấn đề về cấu hình. Nỗ lực này đã thất bại trong lần thử đầu tiên, lần thứ hai và lần thứ ba. Hai code base này, mặc dù rất giống nhau, vẫn còn quá nhiều điểm khác biệt để có thể tái tích hợp – đặc biệt là trong môi trường thị trường thay đổi nhanh chóng vào thời điểm đó.
Trong khi đó, “Tiger Team” vẫn đang cố gắng viết lại mọi thứ trong C và UNIX, nhận ra rằng họ cũng phải xử lý với cả sự khác nhau giữa Châu Âu / Hoa Kỳ này. Và tất nhiên, tiến độ của họ không thể nào mà đẩy nhanh lên được.
Kết luận SAC
Tôi có thể kể cho bạn nghe nhiều câu chuyện khác về hệ thống này, nhưng tôi quá nản để tiếp tục. Chỉ cần nói rằng nhiều bài học khó khăn trong cuộc đời làm phần mềm của tôi đã học được khi tôi đã chìm trong đống mã hợp ngữ khủng khiếp của SAC.
Ngôn ngữ C
Phần cứng máy tính 8085 mà chúng tôi sử dụng trong dự án 4-Tel Micro đã mang lại cho chúng tôi một nền tảng máy tính chi phí tương đối thấp có thể sử dụng cho nhiều dự án khác nhau được nhúng vào môi trường công nghiệp. Chúng tôi có thể nạp nó với 32K RAM và 32K ROM khác, và chúng tôi có một cỗ máy cực kỳ linh hoạt và mạnh mẽ để điều khiển các thiết bị ngoại vi. Những gì chúng tôi không có là một ngôn ngữ linh hoạt và thuận tiện để lập trình cỗ máy này. Trình biên dịch hợp ngữ 8085 chỉ đơn giản là không hề thú vị khi viết mã.
Trên hết, trình biên dịch hợp ngữ mà chúng tôi đang sử dụng được viết bởi các lập trình viên của chính chúng tôi. Nó chạy trên máy tính M365 của chúng tôi, sử dụng hệ điều hành băng từ như được mô tả trong phần “Cắt Laser”.
Như định mệnh đã xảy ra, kỹ sư phần cứng hàng đầu của chúng tôi đã thuyết phục CEO của chúng tôi rằng chúng tôi cần một chiếc máy tính thực sự. Anh ấy thực sự không biết mình sẽ làm gì với nó, nhưng anh ấy có rất nhiều ảnh hưởng chính trị. Vì vậy, chúng tôi đã được mua một chiếc PDP-11/60.
Tôi, một lập trình viên tầm thường vào thời điểm đó, đã rất ngạc nhiên. Tôi biết chính xác những gì tôi muốn làm với chiếc máy tính đó. Tôi đã xác định rằng đây sẽ là máy của tôi.
Khi sách hướng dẫn đến tay, nhiều tháng trước khi giao máy, tôi đã mang chúng về nhà và ngấu nghiến nó. Vào thời điểm máy tính được giao, tôi đã biết cách vận hành cả phần cứng và phần mềm ở mức độ quen thuộc – ít nhất là quen thuộc như việc học ở nhà có thể làm được.
Tôi đã giúp viết đơn đặt hàng. Đặc biệt, tôi đã chỉ định dung lượng lưu trữ đĩa mà máy tính mới sẽ có. Tôi quyết định chúng tôi nên mua hai ổ đĩa có thể tháo rời, mỗi chiếc 25 megabyte[4].
Năm mươi megabyte! Số này dường như là vô hạn rồi! Tôi nhớ khi đi bộ ngang qua các hành lang của văn phòng, vào đêm khuya, miệng lẩm nhẩm như mụ Phù Thủy Xấu Xa của Miền Tây (Wicked Witch of the West): “Năm mươi megabyte! Hahahahahahahahahah! ”
Tôi đã yêu cầu người quản lý cơ sở xây dựng một căn phòng nhỏ để chứa sáu thiết bị đầu cuối VT100. Tôi trang trí nó bằng những bức tranh về không gian. Các lập trình viên phần mềm của chúng tôi sẽ sử dụng căn phòng này để viết và biên dịch mã.
Khi chiếc máy đó đến nơi, tôi đã mất vài ngày để thiết lập nó, nối dây tất cả các thiết bị đầu cuối và đưa mọi thứ vào hoạt động. Đó là một niềm vui – một tình yêu lao động.
Chúng tôi đã mua các trình biên dịch hợp ngữ tiêu chuẩn cho 8085 từ Boston Systems Office và chúng tôi đã dịch mã 4-Tel Micro sang cú pháp đó. Chúng tôi đã xây dựng một hệ thống biên dịch chéo cho phép chúng tôi nạp các file nhị phân đã biên dịch từ PDP-11 xuống môi trường phát triển 8085 và trình ghi ROM của chúng tôi. Và tất cả đều hoạt động muột mà.
C
Nhưng chúng tôi vẫn gặp vấn đề về việc sử dụng trình biên dịch hợp ngữ 8085. Đó không phải là thứ khiến tôi hài lòng. Tôi đã nghe nói rằng có ngôn ngữ “mới” được sử dụng nhiều tại Bell Labs. Họ gọi nó là “C.” Vì vậy, tôi đã mua một bản sao Ngôn ngữ lập trình C của Kernighan và Ritchie. Giống như các hướng dẫn sử dụng PDP-11 vài tháng trước, tôi đã đọc ngấu nghiến cuốn sách.
Tôi đã rất ngạc nhiên bởi sự thanh lịch đơn giản của ngôn ngữ này. Nó không hy sinh sức mạnh của hợp ngữ, mà vẫn cung cấp quyền truy cập vào sức mạnh đó với một cú pháp thuận tiện hơn nhiều. Tôi đã bị thuyết phục.
Tôi đã mua một trình biên dịch C từ Whitesmiths và để nó chạy trên PDP-11. Đầu ra của trình biên dịch là cú pháp trình hợp dịch tương thích với trình biên dịch Boston Systems Office 8085. Như vậy, chúng tôi đã có một con đường để đi từ C đến phần cứng 8085!
Bây giờ vấn đề duy nhất là thuyết phục một nhóm lập trình viên hợp ngữ nhúng rằng họ nên sử dụng C. Nhưng đó là một câu chuyện ác mộng cho một khoảng thời gian khác …
[1] Vâng, tôi hiểu đó là oxymoron.
[2] Chúng có một cửa sổ bằng nhựa trong suốt nhỏ cho phép bạn nhìn thấy chip silicon bên trong và cho phép tia cực tím xóa dữ liệu.
[3] Có, tôi biết rằng khi phần mềm được ghi vào ROM, nó được gọi là firmware — nhưng thậm chí firmware thực sự vẫn mềm.
[4] RKO7